java 入土--集合詳解( 二 )

SetSet 接口也是單例的,是無序的,增加和取出順序是不確定的,無索引不可重復,null 最多有一個 。繼承自 Collection 接口,Set 的方法與 List 的方法相差不大,但不能用索引的方式遍歷 。
HashSetHashSet 實現 Set 接口,其底層是 HashMap,由于 HashMap 的底層是數組+鏈表+紅黑樹,所以 HashSet 的底層就是數組+鏈表+紅黑樹,存儲時,底層通過 equles()和 hash()方法來確定存儲位置,所以存入與取出的順序不一致 。

java 入土--集合詳解

文章插圖
HashSet 的初始大小是 16 長度大小的數組,當數組的容量達到 16 的 0.75 倍時,會進行提前擴容,也就是數組在滿足 12 時,會進行擴容,其擴容倍數為 2 倍 。
注:當數組長度大于 64,同時鏈表長度大于 8 時,hashSet 變為紅黑樹存儲,優化存儲結構 。
要注意重寫 hashCode 與 equlse 方法才能使不同對象的相同內容實現不重復 。
LinkedHashSet父類是 HashSet,底層是 LinkedHashMap,維護了一個數組+雙向鏈表 , 也是以 hsash 值來確定位置 。存儲結構是雙向鏈表 , 所以是有序的,不允許有雙向鏈表 。
  • 擴容機制
    • 第一次時,數組 table 擴容到 16,底層是存儲在 LinkedHashMap$Entry 對象節點上 , 數組是 HashMap$Node[],在數組中存放 LinkedHashMap$Entry 對象 。
TreeSet底層是 TreeMap , 可以進行排序,當我們使用無參構造器,創建 TreeSet 時,仍然是無序的.當我們需要按照某種方式進行排序時,需要使用 TreeSet 提供的一個構造器 , 可以傳入一個比較器[匿名內部類]并指定排序規則
//具體的比較規則還需根據實際進行重寫,這里舉一個例子 。TreeSet<Object> objects = new TreeSet<>(new Comparator<Object>() {@Overridepublic int compare(Object o1, Object o2) {return o1.toString().compareTo(o2.toString());}});TreeSet 接口間接實現了 Set 接口,是一個有序的集合,它的作用是提供有序的 Set 集合
TreeSet 的特點
  1. 元素有序:按照構造方法進行排序
    1. TreeSet()根據元素的自然排序進行排序
    2. TreeSet(Comparator comparator):根據指定的比較器進行排序,自然排序需要在類中實現 comparator 接口
      java 入土--集合詳解

      文章插圖
  2. 沒有索引,不能用普通 for 循環遍歷
  3. 繼承 Set 集合,無重復元素
TreeSet<Integer> ts = new TreeSet<Integer>();//自然排序ts.add(10);ts.add(20);ts.add(4);for (Integer i : ts) {System.out.println(i);//輸出4,10,20}
java 入土--集合詳解

文章插圖
通過指定比較器進行排序
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {//o1是o2是的下一個int num = o1.getAge() - o2.getAge();int num2 = num == 0 ? o1.getName().compareTo(o2.getName()) : num;return num2;}});//創建對象Student s1 = new Student("maoyaning", 32);Student s2 = new Student("asdfds", 53);Student s3 = new Student("khljn", 24);Student s4 = new Student("sdfwfds",24);//添加集合元素ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);for (Student s : ts) {System.out.println(s.getName() + " " + s.getAge());}Set 兩種循環遍歷:由于 Set 集合的底層,所以無法用下標遍歷,因此只能用增強 for 和 iterator 進行遍歷
  1. 增強 for
for (String str : set) {System.out.println(str);}
  1. 迭代器
Set set = new HashSet();Iterator it = set.iterator();while (it.hasNext()) {String str = it.next();System.out.println(str);}Map 接口Map<K,V>,是一個接口,將鍵映射到值,不能包含重復的鍵 , 每個鍵只能映射一個值 。
java 入土--集合詳解

文章插圖
Map 接口用于存儲具有映射關系的數據,key-value 。
底層:
  • 在創建 Map 集合時,Map 的底層會創建 EntrySet 集合,用于存放 Entry 對象,而一個 Entry 對象具有 key 和 value,同時創建 Set 數組指向 key,創建 collection 對象指向 value,取出時 , 實際上是調用 set 和 collection 數組的地址進行調用 , 從而提高遍歷效率 。
在進行 map 元素添加時,map.put()方法在底層上是通過 hashcode 與 equals 方法進行比較,當 key 相同時 , 會進行替換 。要注意的是,HashSet 的底層也是 HashMap,也是以鍵值對的形式進行存儲的,只不過在進行錄入時,把 value 值設置為一個常數,所以在 HashSet 中 , 不能存儲相同的值(會進行覆蓋) 。而在 Map 中 , 可以存儲相同的 value 值,但是 Key 不能重復,也就是說在 Map 中,key 可以有 null,但是只能有一個 , value 可以有多個 null 。

推薦閱讀