Java 知識點整理-12.Java集合框架 Map+HashMap+LinkedHashMap+TreeMap+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。