Set 表示由無重複對象組成的集合,也是集合框架中重要的一種集合類型,直接擴展自 Collection 接口。在一個 Set 中,不能有兩個引用指向同一個對象,或兩個指向 null 的引用。若是對象 a 和 b 的引用知足條件 a.equals(b),那麼這兩個對象也不能同時出如今集合中。java
一般 Set 是不要求元素有序的,但也有一些有序的實現,如 SortedMap 接口、LinkedHashSet 接口等。安全
Set 的具體實現一般都是基於 Map 的。由於 Map 中鍵是惟一的,於是在基於 Map 實現 Set 時,只須要關心 Map 中的鍵,和鍵關聯的值不須要有意義,使用一個任意的對象「佔位」便可。咱們在前面分析 Map 中的迭代器時,KeySet() 方法獲得的就是一個 Set。多線程
前面咱們分析過 Map 接口的幾個具體實現,通用的實現 HahsMap
,插入或訪問序的 LinkedHashMap
, 按照鍵升序的 TreeMap
。一樣,在 Set 的具體實現中,也有 HashSet
、 LinkedHashSet
和 TreeSet
等,分別和 Map 一一對應,它們的特性對應着相應的 Map 實現的特性。下面基於 HashSet 的實現作一個簡略的介紹。框架
1 |
|
從成員變量和構造方法能夠清楚地看到,內部使用了一個 HahsMap,同時定義了一個無心義的空的靜態 Object 對象(佔用8byte) PRESENT。既然 map 中和鍵關聯的值沒有意義,爲何不乾脆使用 null 呢?咱們看一下 add() 方法:性能
1 |
public boolean add(E e) { |
Map 的 put() 方法在添加一個新的鍵時會返回 null,在更新一個已經存在的鍵關聯的值時會返回舊值。於是 Set 中的 add() 方法能夠據此判斷新加入的元素是否改變了集合,若是改變了就返回 true。於是 PRESENT 不可使用 null 。this
其它的方法這裏簡單地列一下,都是基於 map 實現的:spa
1 |
public boolean contains(Object o) { |
Set 的內部一般是基於 Map 來實現的,Map 中的 Key 構成了 Set,而 Value 所有使用一個無心義的 Object 。 Set 的特徵與其內部的 Set 的特徵是一致的。基於 HashMap 的 HashSet 是無序時的最佳通用實現,基於 LinkedHashMap 的 LinkedHashSet 保留插入或訪問的順序,基於 TreeMap 的 TreeSet 能夠按照元素升序排列,要求元素實現 Comaprable 接口或自定義比較器。線程
HashSet , LinkedHashSet, TreeSet 都不是線程安全的,在多線程環境下使用時要注意同步問題。code
CopyOnWriteArraySet 是一個線程安全的實現,可是並非基於 Map 實現的,而是經過 CopyOnWriteArrayList 實現的。使用 addIfAbsent() 方法進行去重,性能比較通常。對象