JDK1.8原始碼(八)——java.util.HashSet 類
在上一篇部落格,我們介紹了 Map 集合的一種典型實現 HashMap ,在 JDK1.8 中,HashMap 是由 陣列+連結串列+紅黑樹構成,相對於早期版本的 JDK HashMap 實現,新增了紅黑樹作為底層資料結構,在資料量較大且雜湊碰撞較多時,能夠極大的增加檢索的效率。瞭解 HashMap 的具體實現後,我們再來介紹由 HashMap 作為底層資料結構實現的一種資料結構——HashSet。(如果不瞭解 HashMap 的實現原理,建議先看看 HashMap,不然直接看 HashSet 是很難看懂的)
1、HashSet 定義
HashSet 是一個由 HashMap 實現的集合。元素無序且不能重複。
1 public class HashSet<E> 2 extends AbstractSet<E> 3 implements Set<E>, Cloneable, java.io.Serializable
和前面介紹的大多數集合一樣,HashSet 也實現了 Cloneable 介面和 Serializable 介面,分別用來支援克隆以及支援序列化。還實現了 Set 介面,該介面定義了 Set 集合型別的一套規範。
2、欄位屬性
1 //HashSet集合中的內容是通過 HashMap 資料結構來儲存的 2private transient HashMap<E,Object> map; 3 //向HashSet中新增資料,資料在上面的 map 結構是作為 key 存在的,而value統一都是 PRESENT 4 private static final Object PRESENT = new Object();
第一個定義一個 HashMap,作為實現 HashSet 的資料結構;第二個 PRESENT 物件,因為前面講過 HashMap 是作為鍵值對 key-value 進行儲存的,而 HashSet 不是鍵值對,那麼選擇 HashMap 作為實現,其原理就是儲存在 HashSet 中的資料 作為 Map 的 key,而 Map 的value 統一為 PRESENT(下面介紹具體實現時會了解)。
3、建構函式
①、無參構造
1 public HashSet() { 2 map = new HashMap<>(); 3 }
直接 new 一個 HashMap 物件出來,採用無參的 HashMap 建構函式,具有預設初始容量(16)和載入因子(0.75)。
②、指定初始容量
1 public HashSet(int initialCapacity) { 2 map = new HashMap<>(initialCapacity); 3 }
③、指定初始容量和載入因子
1 public HashSet(int initialCapacity, float loadFactor) { 2 map = new HashMap<>(initialCapacity, loadFactor); 3 }
④、構造包含指定集合中的元素
1 public HashSet(Collection<? extends E> c) { 2 map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); 3 addAll(c); 4 }
集合容量很好理解,這裡我介紹一下什麼是載入因子。在 HashMap 中,能夠儲存元素的數量就是:總的容量*載入因子 ,新增一個元素時,如果HashMap集合中的元素大於前面公式計算的結果了,那麼就必須要進行擴容操作,從時間和空間考慮,載入因子一般都選預設的0.75。
4、新增元素
1 public boolean add(E e) { 2 return map.put(e, PRESENT)==null; 3 }
通過 map.put() 方法來新增元素,在上一篇部落格介紹該方法時,說明了該方法如果新插入的key不存在,則返回null,如果新插入的key存在,則返回原key對應的value值(注意新插入的value會覆蓋原value值)。
也就是說 HashSet 的 add(E e) 方法,會將 e 作為 key,PRESENT 作為 value 插入到 map 集合中,如果 e 不存在,則插入成功返回 true;如果存在,則返回false。
5、刪除元素
1 public boolean remove(Object o) { 2 return map.remove(o)==PRESENT; 3 }
呼叫 HashMap 的remove(Object o) 方法,該方法會首先查詢 map 集合中是否存在 o ,如果存在則刪除,並返回該值,如果不存在則返回 null。
也就是說 HashSet 的 remove(Object o) 方法,刪除成功返回 true,刪除的元素不存在會返回 false。
6、查詢元素
1 public boolean contains(Object o) { 2 return map.containsKey(o); 3 }
呼叫 HashMap 的 containsKey(Object o) 方法,找到了返回 true,找不到返回 false。
7、遍歷元素
1 HashSet<Integer> set = new HashSet<>(); 2 set.add(1); 3 set.add(2); 4 //增強for迴圈 5 for(Integer i : set){ 6 System.out.println(i); 7 } 8 //普通for迴圈 9 Iterator<Integer> iterator = set.iterator(); 10 while (iterator.hasNext()){ 11 System.out.println(iterator.next()); 12 }