1. 程式人生 > >Java 知識點整理-12.Java集合框架 Map+HashMap+LinkedHashMap+TreeMap+Collections+泛型固定下邊界+集合框架總結

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。