源码分析-HashSet、LinkedHashSet
基本特性
HashSet的是依靠組合一個HashMap實現的。然后講大部分任務都委托給HashMap完成。?
當然,HashSet不保證迭代順序與添加順序相同,而且也不保證其順序不變。允許空元素。?
對于其迭代器的迭代效率正比于(HashSet的內元素和HashSet的桶數量之和),因此如果對迭代效率要求比較高,就不要使用過大的初始大小。(這部分從HashSet本身的代碼看不出來,今后分析HashMap的時候再說)?
對于同步特性,當然HashMap本身的不同步的,所以HashSet本身也不是線程安全的,所以如果要保證線程安全至少要用Set s = Collections.synchronizedSet(new HashSet(...));,當然還要注意使用同步包裝器只是限制每次只能一個線程訪問。?
對于迭代器使用的HashMap.keySet.iterator實現的,fail-fast迭代器。?
HashSet本身的內容很少。
如果將任務委托給HashMap
之前說過HashSet內置了一個HashMap的域變量,然后將所有的操作都委托給HashMap,這里的實現實際上就是先定義一個類靜態變量的啞節點,就是PRESENT。然后將其作為HashMAP的值,然后將Set作為Key。這樣就可以講Set的認為委托給HashMap執行。
? ? // Dummy value to associate with an Object in the backing Map
? ? private static final Object PRESENT = new Object();
1
2
初始化
其實構造器也沒有特別的地方,基本上都是把所有的認為委托給HashMap,但是HashSet有兩種實現,分別是是HashSet和LinkedHashSet,也分別對應了HashMap和LinkedHashMap的實現?
為了區別這兩者HashSet中實現了一個默認訪問權限的構造器,然后讓LinkedHashSet繼承HashSet。如果需要使用LinkedHashSet則只要在LinkedHashSet中使用構造器然后在尾部加上true(其實加上false也可以)就可以使用LinkedHashMap來實現。
? ? HashSet(int initialCapacity, float loadFactor, boolean dummy) {
? ? ? ? map = new LinkedHashMap<>(initialCapacity, loadFactor);
? ? }
1
2
3
LinkedHashSet
基本特性
這里與HashSet不同使用了一個雙端隊列實現HashSet。從而實現了有序的排列。LinkedHashSet維護的是插入順序,而且不受重復插入的影響,也就是僅僅以第一次插入操作為準。
客戶端的散列實沒有特殊指定,通常使用HashSet的散列順序,而使用TreeSet則會有稍高的代價。這樣當如果復制元素時依然會保持原先的順序,通常符合使用者習慣。這句話其實我不是很理解。
LinkedHashSet是HashSet的子類,允許空元素,插入包含刪除操作有常數時間復雜度,但是時間會稍多于HashSet因為需要維護雙端隊列。
當然LinkedHashSet的性能會收到初始大小和裝填因子的影響,但是和HashSet有些不同,HashSet元素迭代性能消耗并不受容量的影響,因此初始大小的懲罰沒有HashSet這么大。
實現
實現上實際上沒有任何特殊的地方。只是重寫了構造器。還利用了HashSet的構造器。
---------------------?
作者:千念飛羽?
來源:CSDN?
原文:https://blog.csdn.net/u011518120/article/details/53356076?
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的源码分析-HashSet、LinkedHashSet的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TreeSet源码解析
- 下一篇: HashSet源码解析