Java 知识点整理-12.Java集合框架 Map+HashMap+LinkedHashMap+TreeMap+Collections+泛型固定下边界+集合框架总结

目录

Map集合概述和特点

HashMap

LinkedHashMap

TreeMap

HashMap

Collections类

泛型固定下边界

集合框架总结


Map集合概述和特点

1、Map接口概述:

public interface Map<k, V>,将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。此接口取代了Dictionary类,后者完全是一个抽象类,而不是一个接口。

参数类型:K -此映射所维护的键的类型。 V - 映射值的类型。

java.util包下,使用需要导包。 集合所有接口和类都是在util包下。接口方法均抽象,不能被实例化。

2、Map接口和Collection接口的区别:

Map是双列的,Collection是单列的。Map是双列集合的根接口,Collection是单列集合的根接口。

Map的键是唯一的,Collection的子体系Set也是唯一的。

他们的体系是非常一样的。

Map集合的数据结构值针对键有效(HashMap,键是哈希算法;TreeMap,键是二叉树算法),跟值无关;Collection集合的数据结构是针对元素有效。单列集合底层依赖双列集合,HashSet底层使用的Map,HashSet底层源码:

private static final Object PRESENT = new Object(); //直接创建一个Object对象放在值的位置,但是值的位置不显示,都隐藏掉。这样的好处是,二者都依赖哈希算法,只弄一套就行。双列隐藏一列很简单,但单列变成双列,太难了。
public boolean add(E e) {
        return map.put(e, PRESENT)==null;
}

3、Map集合的功能概述

ⅰ.添加功能:

V put(K key, V value):添加元素,将指定的值与该映射中的指定键相关联(可选操作)。返回值类型与Map接口泛型中值的类型相同。 泛型中使用包装类,不能用基本数据类型。

如果键是第一次存储,就直接存储元素,返回null(其实null被覆盖了)。

如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值。

ⅱ.删除功能:

void clear():移除所有的键值对元素。

V remove(Object key):根据键删除键值对元素,并把值返回。传键删值。

ⅲ.判断功能:

boolean containsKey(Object key):判断集合是否包含指定的键。

boolean containsValue(Object value):判断集合是否包含指定的值。

boolean isEmpty():判断集合是否为空。

ⅳ.获取功能:

Set<Map.Entry<K, V>> entrySet():拿到所有的键值对象。返回是一个Set,里面写Map.Entry<K, V>。

V get(Object key):根据键获取值。有键无值,返回null。

Set<K> keySet():获取集合中所有键的集合。返回值是Set,Set集合里有Iterator()。

Collection<V> values():获取集合中所有值的集合。参数V与值的类型相同。

ⅴ.长度功能:

int size():返回集合中的键值对的个数。一对代表一个元素。

接口Map.Entry<K, V>概述:public static interface Map.Entry<K, V>,映射项(键—值对)。正在封闭的接口:Map<K, V>。解释:Entry<K, V>是Map<K, V>的内部接口。

接口Map.Entry<K, V>方法:

K getKey() 返回与此项对应的键。

V getValue() 返回与此项对应的值。

4、Map集合的遍历之键找值(Map集合的第一种迭代):

通过查看Map集合的api发现没有Iterator方法。

键找值思路:应用keySet()获取所有键的集合。遍历键的集合,获取到每一个键。根据键应用get(Object key)找值。

案例演示:Map集合的遍历之键找值

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Demo2_Iterator {
	public static void main(String[] args) {
		Map<String, Integer> map = new HashMap<>();
		map.put("张三", 23);
		map.put("李四", 24);
		map.put("王五", 25);
		map.put("赵六", 26);
		
		/*Integer i = map.get("张三");				//根据键获取值
		System.out.println(i);*/
		
		//迭代器遍历
		/*Set<String> keySet = map.keySet();			//获取所有键的集合
		Iterator<String> it = keySet.iterator();	//获取迭代器
		while(it.hasNext()) {						//判断集合中是否有元素
			String key = it.next();					//获取每一个键
			Integer value = map.get(key);			//根据键获取值
			System.out.println(key + "=" + value);	//打印键值对
		}*/
		
		//增强for循环遍历
		for(String key : map.keySet()) {			//map.keySet()是所有键的集合
			System.out.println(key + "=" + map.get(key));
		}
	}
}

5、Map集合的遍历之键值对对象 找键和值(Map集合的第二种迭代。比第一种迭代提高效率,节约时间)。

键值对对象 找键和值思路:

应用entrySet()把双列集合的键值对变成单列集合的键值对对象,然后遍历这个单列集合获取每一个键值对对象。根据键值对对象获取键和值。

案例演示:Map集合的遍历之键值对对象找键和值。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Demo3_Iterator {
	public static void main(String[] args) {
		Map<String, Integer> map = new HashMap<>();
		map.put("张三", 23);
		map.put("李四", 24);
		map.put("王五", 25);
		map.put("赵六", 26);
		
		//迭代器遍历
		/*Set<Map.Entry<String, Integer>> entrySet = map.entrySet();	//Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中。即Map中的一对元素变成了Set集合中的一个对象元素。
		Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();	//获取每一个对象。Set集合中存储的每一个Entry对象,所以迭代器与集合泛型一致。
		while(it.hasNext()) {
			Map.Entry<String, Integer> entry = it.next();			//获取每一个Entry对象。父类引用指向子类对象。
//			Entry<String, Integer> entry = it.next();				//直接获取的是子类对象
			String key = entry.getKey();							//根据键值对对象获取键
			Integer value = entry.getValue();						//根据键值对对象获取值
			System.out.println(key + "=" + value);
//			System.out.println(entry.getKey() + "=" + entry.getValue());
		}*/
		//增强for循环遍历
		for (Entry<String, Integer> entry : map.entrySet()) {		//Map.Entry<String, Integer>没加Map.也可以。Entry是Map.Entry的子类对象,Entry对象代表的是键值对对象,通过Entry对象获取键和值。
			System.out.println(entry.getKey() + "=" + entry.getValue());
		}
	}
}

HashMap

1、案例演示:HashMap集合 键是Student 值是String的案例。双列集合存储自定义对象,保证键的唯一。

/**
 * 案例演示:HashMap集合 键是Student 值是String的案例。
 * 分析:键是学生对象,代表每一个学生。值是字符串对象,代表学生归属地。
 */
public class Demo5_HashMap {
	public static void main(String[] args) {
		HashMap<Student, String> hm = new HashMap<>();
		hm.put(new Student("张三", 23), "北京");
		hm.put(new Student("张三", 23), "上海");
		hm.put(new Student("李四", 24), "广州");
		hm.put(new Student("王五", 25), "深圳");
		
		System.out.println(hm);
	}
}
//HashMap的父类AbstractMap<K,V>重写了toString(),源代码:
/*public String toString() {
    Iterator<Entry<K,V>> i = entrySet().iterator();		//拿到每一个Entry对象放到迭代器里面
    if (! i.hasNext())									//如果迭代器为空,没有元素
        return "{}";									//返回{}

    StringBuilder sb = new StringBuilder();				//如果有元素,创建StringBuilder
    sb.append('{');										//添加{
    for (;;) {											//无限循环
        Entry<K,V> e = i.next();						//拿到每一个Entry对象
        K key = e.getKey();								//拿到键
        V value = e.getValue();							//拿到值
        sb.append(key   == this ? "(this Map)" : key);	//不断添加
        sb.append('=');
        sb.append(value == this ? "(this Map)" : value);
        if (! i.hasNext())
            return sb.append('}').toString();			//添加},再掉toString()转化成字符串
        sb.append(',').append(' ');
    }
}*/

自定义类:

public class Student {
	private String name;
	private int age;
	public Student() {
		super();
		
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
}

LinkedHashMap

1、LinkedHashMap的概述:

public class LinkedHashMap<K, V> extends HashMap<K, V> implements Map<K, V>,哈希表和链表实现的Map接口,具有可预测的迭代次序。

java.util包下,使用需要导包。

2、案例演示:LinkedHashMap的使用。

import java.util.LinkedHashMap;

public class Demo6_LinkedHashMap {
	public static void main(String[] args) {
		LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
		lhm.put("张三", 23);
		lhm.put("李四", 24);
		lhm.put("赵六", 26);
		lhm.put("王五", 25);
		
		System.out.println(lhm);
	}
}

3、LinkedHashMap的特点:

底层是链表实现的,可以保证怎么存就怎么取。属于HashMap派系,保证键的唯一。


TreeMap

1、TreeMap概述:

public class TreeMap<K, V> extends AbstractMap<K, V> implements NaigableMap<k, V>, Cloneable, Serializable,一个红黑树基于NavigableMap实现。

2、TreeMap的构造方法:

TreeMap(Comparator<? super K> comparator) 构造一个新的,空的树映射,该映射根据给定的比较器进行排序。

3、案例演示:TreeMap集合 键是Student 值是String的案例。键是二叉树排序。

import java.util.Comparator;
import java.util.TreeMap;

import com.bean.Student;

/**
 * 	案例演示:TreeMap集合 键是Student 值是String的案例。
 */
public class Demo7_TreeMap {
	public static void main(String[] args) {
		//按照传入的比较器进行比较
		TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {
			public int compare(Student s1, Student s2) {
				int num = s1.getName().compareTo(s2.getName());		//按照姓名比较
				return num == 0 ? s1.getAge() - s2.getAge() : num;
			}
		});
		tm.put(new Student("张三", 23), "北京");
		tm.put(new Student("李四", 13), "上海");
		tm.put(new Student("王五", 33), "广州");
		tm.put(new Student("赵六", 43), "深圳");
		
		System.out.println(tm);
		//让对象自身具有比较性,让自定义类实现了Comparable接口,并重写了compareTo()。
		/*TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {
			public int compare(Student s1, Student s2) {
				int num = s1.getName().compareTo(s2.getName());		//按照姓名比较
				return num == 0 ? s1.getAge() - s2.getAge() : num;
			}
		});
		tm.put(new Student("张三", 23), "北京");
		tm.put(new Student("李四", 13), "上海");
		tm.put(new Student("王五", 33), "广州");
		tm.put(new Student("赵六", 43), "深圳");
		
		System.out.println(tm);*/
	}
}

自定义类:

public class Student implements Comparable<Student>{
	private String name;
	private int age;
	public Student() {
		super();
		
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int compareTo(Student o) {
		int num = this.age - o.age;							//以年龄为主要条件
		return num == 0 ? this.name.compareTo(o.name) : num;//以姓名为次要条件
	}
	
}

HashMap

2、案例演示:需求:统计字符串中每个字符出现的次数

import java.util.HashMap;

/**
 * 	需求:统计字符串中每个字符出现的次数
 * 	分析:
 * 	1.定义一个需要被统计字符的字符串。
 * 	2.将字符串转换为字符数组。
 * 	3.定义双列集合,存储字符串中字符以及字符出现的次数。
 * 	4.遍历字符数组获取每一个字符,并将字符存储在双列集合中。
 * 	5.存取过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储;如果集合中包含这个键,就将值加1存储。
 * 	6.打印双列集合获取字符出现的次数。
 */
public class Test1 {
	public static void main(String[] args) {
		//1.定义一个需要被统计字符的字符串。
		String s = "aaaabbbbcccccccccccddc";
		//2.将字符串转换为字符数组。
		char[] arr = s.toCharArray();
		//3.定义双列集合,存储字符串中字符以及字符出现的次数。没有任何要求,首选HashMap。LinkedHashMap底层链表实现的,得保证怎么存怎么取。TreeMap要排序。HashMap是直接往里扔。
		HashMap<Character, Integer> hm = new HashMap<>();
		//4.遍历字符数组获取每一个字符,并将字符存储在双列集合中。
		for(char c : arr) {
			//5.存取过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储;如果集合中包含这个键,就将值加1存储。
			/*if(!hm.containsKey(c)) {		//如果不包含这个键。
				hm.put(c, 1);				//把键和值为一存储。
			}else {							//如果包含这个键。
				hm.put(c, hm.get(c) + 1);	//把键和值加一存储。
			}*/
			hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);  //代码优化,三元运算符
		}
		//6.打印双列集合获取字符出现的次数。
		for (Character key : hm.keySet()) {	//自动拆箱,前面用char也可以.hm.keySet()代表所有键的集合。
			System.out.println(key + "=" + hm.get(key));		//hm.get(key)代表根据键获取值。
		}
	}
}

3、案例演示:集合嵌套之HashMap嵌套HashMap。

import java.util.HashMap;

import com.bean.Student;

/**
 *	案例演示:集合嵌套之HashMap嵌套HashMap。
 *	需求:将第八十八个班级定义成一个双列集合,键是学生对象,值是学生的归属地。
 *		将第九十九个班级定义成一个双列集合,键是学生对象,值是学生的归属地。
 *		二者都是班级对象,所以为了便于统一管理,将二者添加到学校集合中。
 */
public class Demo8_HashMapHashMap {
	public static void main(String[] args) {
		//定义第88个班级
		HashMap<Student, String> hm88 = new HashMap<>();  //Student类已经重写了hashCode()和equals()
		hm88.put(new Student("张三", 23), "北京");
		hm88.put(new Student("李四", 24), "北京");
		hm88.put(new Student("王五", 25), "上海");
		hm88.put(new Student("赵六", 26), "广州");
		
		//定义第99个班级
		HashMap<Student, String> hm99 = new HashMap<>();  
		hm99.put(new Student("唐僧", 1023), "北京");
		hm99.put(new Student("孙悟空", 1524), "北京");
		hm99.put(new Student("猪八戒", 1125), "上海");
		hm99.put(new Student("沙和尚", 1226), "广州");
		
		//定义学校,键是集合对象,值是班级。集合中嵌套集合。
		HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
		hm.put(hm88, "第88个班级");
		hm.put(hm99, "第99个班级");
		
		//遍历双列集合
		for (HashMap<Student, String> h : hm.keySet()) {	//hm.keySet()代表的是双列集合中键的集合
			String value = hm.get(h);						//get(h)根据键对象获取值对象
			//遍历键的双列集合对象
			for (Student key : h.keySet()) { 				//h.keySet()获取集合中所有的学生键对象
				String value2 = h.get(key);
				System.out.println(key + " " + value2 + " " + value);
			}
		}
	}
}

4、面试题:HashMap和Hashtable的区别。

HashTable概述:

public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, Cloneable, Serializable,该类实现了一个哈希表,它将键映射到值。 任何非null对象都可以用作键值或值。

为了从散列表成功存储和检索对象,用作键的对象必须实现hashCode方法和equals方法。

java.util包下,使用需要导包。

命运类似vector从版本1.0出现,1.2改进实现List接口。Hashtable改进实现Map接口,被HashMap替代掉了。

第二单词首字母小写。

HashMap和Hashtable的共同点:

底层都是哈希算法。都是双列集合。

HashMap和Hashtable的区别:

Hashtable是JDK1.0版本出现的,是线程安全的效率低;HashMap是JDK1.2版本出现的,是线程不安全的效率高

Hashtable可以存储null键和null值,HashMap可以存储null键和null值。

案例演示 :HashMap和Hashtable的区别。

import java.util.HashMap;
import java.util.Hashtable;

public class Demo9_Hashtable {
	public static void main(String[] args) {
		HashMap<String, Integer> hm = new HashMap<>();	//为了后续代码能够继续执行,所以改进成能够存储null键和null值。
		hm.put(null, 23);			//存储null键
		hm.put("李四", null);			//存储null值
		System.out.println(hm);
		
/*		Hashtable<String, Integer> ht = new Hashtable<>();
//		ht.put(null, 23);			//NullPointerException
//		ht.put("李四", null);			//NullPointerException
		System.out.println(ht);*/
	}
}

Collections类

1、Collections类概述:

public class Collections extends Object,此类仅由静态方法组合或返回集合。它包含对集合进行操作的多态算法,“包装器”,返回由指定集合支持的新集合,以及其他一些可能的和最终的。

如果提供给它们的集合或类对象为null,则此类的方法都抛出一个NullPointerException 。

java.util包下,使用需要导包。

针对集合操作的工具类。类似于Arrays工具类 操作数组。

属性、方法均静态,构造方法被私有了。当一个类中所有的方法都是静态的,会私有这个类的构造方法。目的是不让其他类创建本类对象,直接类名.调用该类属性、方法。

2、Collections部分成员方法:

public static <T extends Comparable<? super T>> void sort(LIst<T> list) 根据其元素的natural ordering,按照升序排列指定的列表。列表中的所有元素必须实现Comparable接口。此外,列表中的所有元素都必须相互可比较 (即e1.compareTo(e2)不能为ClassCastException中的任何元素e1和e2 )。

这种保证是稳定的 :等同的元素将不会被排序作为排序的结果。

指定的列表必须是可修改的,但不能调整大小。

public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key) 使用二叉搜索算法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行生序排序(通过sort(List)方法)。如果没有对列表进行排序,则结果是不确定的。 如果列表包含多个与指定对象相等的元素,则不能保证将找到哪个元素。

返回:如果搜索键包含在列表中,则返回搜索键的索引;否则返回(-(插入点)-1)。插入点被定义为将键插入列表的那一点:即第一个大于此键的元素索引;如果列表中的所有元素都小于指定的键,则为list.size()。注意,这保证了当且仅当此键被找到时,返回的值将>=0;

public static <T extends Object & Comparable<? super T>> T max(Collection<?> coll) 根据其元素的自然顺序返回给定集合的最大元素。集合中的所有元素必须实现Comparable接口。此外,集合中的所有元素必须相互可比较 (即e1.compareTo(e2)不得为集合中的任何元素e1和e2投掷ClassCastException)。先对集合进行排序,再获取最后一个元素。默认按照以实现的compareTo()去排序,String类实现了compareTo()。

该方法遍历整个集合,因此它需要与集合的大小成比例的时间。

参数:coll - 要确定其最大元素的集合。

public static void reverse(List<?> list) 反转指定列表中元素的顺序。

public static void shuffle(List<?> list) 使用默认的随机源随机排列指定的列表。 所有排列都以大致相等的可能性发生。随机置换,可以用来洗牌。

3、案例演示:模拟斗地主洗牌和发牌,牌没有排序。

import java.util.ArrayList;
import java.util.Collections;

/**
 * 	案例演示:模拟斗地主洗牌和发牌,牌没有排序。
 * 	分析:
 * 	1.买一副扑克,其实就是自己创建一个集合对象,将扑克牌存储进去。
 *  2.洗牌。
 *  3.发牌。
 *  4.看牌。
 */
public class Test2 {
	public static void main(String[] args) {
		//1.买一副扑克,其实就是自己创建一个集合对象,将扑克牌存储进去。
		String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
		String[] color = {"红桃","黑桃","方片","梅花"};
		ArrayList<String> poker = new ArrayList<>();
		
		//拼接花色和数字
		for(String s1 : color) {
			for(String s2 : num) {
				poker.add(s1.concat(s2));	//连接两个字符串
			}
		}
		poker.add("小王");
		poker.add("大王");
		//2.洗牌。
		Collections.shuffle(poker);
		//3.发牌。
		ArrayList<String> gaojin = new ArrayList<>();
		ArrayList<String> longwu = new ArrayList<>();
		ArrayList<String> me = new ArrayList<>();
		ArrayList<String> dipai = new ArrayList<>();
		
		for (int i = 0; i < poker.size(); i++){
			if(i >= poker.size() - 3) {
				dipai.add(poker.get(i));       //将三张底牌存储在底牌集合中
			}else if(i % 3 == 0) {
				gaojin.add(poker.get(i));
			}else if(i % 3 == 1) {
				longwu.add(poker.get(i));
			}else {
				me.add(poker.get(i));
			}
		}
		//4.看牌。
		System.out.println(gaojin);
		System.out.println(longwu);
		System.out.println(me);
		System.out.println(dipai);
	}
}

4、案例演示:模拟斗地主洗牌和发牌并对牌进行排序的代码实现。

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

/**
 * 	案例演示:模拟斗地主洗牌和发牌并对牌进行排序的代码实现。
 * 	分析:
 * 	1.买一副扑克,其实就是自己创建一个集合对象,将扑克牌存储进去。
 *  2.洗牌。
 *  3.发牌。
 *  4.看牌。
 */
public class Test3 {
	public static void main(String[] args) {
		//1.买一副扑克,其实就是自己创建一个集合对象,将扑克牌存储进去。
		String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
		String[] color = {"红桃","黑桃","方片","梅花"};
		HashMap<Integer, String> hm = new HashMap<>();		//存储索引和扑克牌
		ArrayList<Integer> list = new ArrayList<>();		//存储索引,方便洗牌
		int index = 0;
		
		//拼接扑克牌,并将索引和扑克牌存储在hm中				
		for(String s1 : num) {								//获取数字
			for(String s2 : color) {						//获取颜色
				hm.put(index, s2.concat(s1));
				list.add(index);							//将索引0到51添加到list集合中
				index++;
			}
		}
		hm.put(index, "小王");									//将小王添加到双列集合中
		list.add(index);									//将索引52添加到list集合中
		index++;											
		hm.put(index, "大王");									//将大王添加到双列集合中
		list.add(index);									//将索引53添加到list集合中
		
		//2.洗牌。
		Collections.shuffle(list);
		//3.发牌。
		TreeSet<Integer> gaojin = new TreeSet<>();
		TreeSet<Integer> longwu = new TreeSet<>();
		TreeSet<Integer> me = new TreeSet<>();
		TreeSet<Integer> dipai = new TreeSet<>();
		
		for(int i = 0; i < list.size(); i++) {
			if(i >= list.size() - 3) {
				dipai.add(list.get(i));						//将三张底牌存储在底牌集合中
			}else if(i % 3 == 0) {
				gaojin.add(list.get(i));
			}else if(i % 3 == 1) {
				longwu.add(list.get(i));
			}else {
				me.add(list.get(i));
			}
			
		}
		//4.看牌。
		lookPoker(hm, gaojin, "高进");
		lookPoker(hm, longwu, "龙五");
		lookPoker(hm, me, "冯佳");
		lookPoker(hm, dipai, "底牌");
	}
	/**
	 * 	看牌
	 *  1.返回值类型void
	 *  2.参数列表HashMap, TreeSet, String name
	 */
	public static void lookPoker(HashMap<Integer, String> hm, TreeSet<Integer> ts, String name) {
		System.out.print(name + "的牌是:");
		for(Integer i : ts) {					//i代表双列集合中的每一个键
			System.out.print(hm.get(i) + " ");  //通过键获取值
		}
		System.out.println();
	} 
}


泛型固定下边界

1、演示:? super E

import java.util.Comparator;
import java.util.TreeSet;

import com.bean.BaseStudent;
import com.bean.Student;

/**
 * 	泛型固定下边界 ? super E
 *	泛型固定上边界 ? extends E 
 */
public class Demo2_Genric {
	public static void main(String[] args) {
		/*ArrayList<Student> list1 = new ArrayList<>();
		list1.add(new Student("张三", 23));
		list1.add(new Student("李四", 24));
		
		ArrayList<BaseStudent> list2 = new ArrayList<>();
		list2.add(new BaseStudent("王五", 25));
		list2.add(new BaseStudent("赵六", 26));
		
		list1.addAll(list2);			//可以把子类对象添加到父类的集合里面去 ? extends E 固定了上边界是Student,下边界是Student子类,可以是BaseStudent,也可以是其他Student
*/
		TreeSet<Student> ts1 = new TreeSet<>(new CompareByAge());
		ts1.add(new Student("张三", 33));
		ts1.add(new Student("李四", 13));
		ts1.add(new Student("王五", 23));
		ts1.add(new Student("赵六", 43));
		
		TreeSet<BaseStudent> ts2 = new TreeSet<>(new CompareByAge());	//可以使用父类的比较器进行排序 ? super E是拿出来。 ?extends E是放进去。把BaseStudent的对象拿出来到父类类型的比较器里去做比较。父类引用指向子类对象。
		ts2.add(new BaseStudent("张三", 33));
		ts2.add(new BaseStudent("李四", 13));
		ts2.add(new BaseStudent("王五", 23));
		ts2.add(new BaseStudent("赵六", 43));
		
		System.out.println(ts2);			
	}
}

class CompareByAge implements Comparator<Student> {						//比较器做完后,可以拿去给Student和Student所有的子类作比较
	public int compare(Student s1, Student s2) {
		int num = s1.getAge() - s2.getAge();
		return num == 0 ? s1.getName().compareTo(s2.getName()) : num;
	}
}

集合框架总结

单列集合Collection

List(存取有序,有索引,可以重复)

    ArrayList:底层是数组实现,线程不安全,查找和修改快,增和删比较慢。

    LinkedList:底层是链表实现,线程安全,增和删比较快,查找和修改比较慢。

    Vector:底层是数组实现,线程安全,无论增删改查都慢。

    查找和修改多:ArrayList;增删多:LinkedList;都多:ArrayList。

Set(存取无序,无索引,不可以重复)

    HashSet:底层是哈希算法实现。

    LinkedHashSet:底层是链表实现,但是也可以保证元素唯一,和HashSet原理一样。

    TreeSet:底层是二叉树实现。

    一般开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet的效率比较高。TreeSet在面试的时候比较多,问你有几种排序方式和这几种排序方式的区别。

双列集合Map

HashMap:底层是哈希算法,针对键。

    LinkedHashMap:底层是链表,针对键。

TreeMap:底层是二叉树算法,针对键。

开发中HashMap比较多。除非对键进行排序,用TreeMap。

猜你喜欢

转载自blog.csdn.net/from_heat/article/details/84364566
今日推荐