Set實現分爲通用實現和專用實現。html
有三種通用的Set實現 — HashSet、TreeSet和LinkedHashSet,使用這三種中的其中一種一般比較簡單。HashSet
比TreeSet
快得多(大多數操做的恆定時間與對數時間),但不提供排序保證,若是須要使用SortedSet
接口中的操做,或者須要按值排序的迭代,請使用TreeSet
,不然,請使用HashSet
。能夠確定的是,大多數狀況下你最終都會使用HashSet
。java
LinkedHashSet
在某種意義上介於HashSet
和TreeSet
之間,做爲哈希表實現,並在其中運行鏈表,它提供了按插入順序排序的迭代(最近插入到最新),而且運行速度幾乎與HashSet
同樣快。LinkedHashSet
實現將其客戶端從HashSet
提供的未指定的、一般混亂的順序中解放出來,而不會增長與TreeSet
相關的成本。segmentfault
關於HashSet
值得記住的一件事是,迭代在條目數和存儲桶數(容量)的總和中是線性的。所以,選擇太高的初始容量會浪費空間和時間,另外一方面,選擇太低的初始容量會在每次被迫增長容量時複製數據結構,從而浪費時間。若是不指定初始容量,則默認值爲16,過去,選擇素數做爲初始容量有一些優點,這再也不是事實,在內部,容量始終四捨五入爲2的冪。初始容量是經過使用int
構造函數指定的,下面的代碼行分配一個初始容量爲64的HashSet
。api
Set<String> s = new HashSet<String>(64);
HashSet
類還有另外一個調整參數,稱爲負載因數,若是你很是在乎HashSet
的空間消耗,請閱讀HashSet
文檔以獲取更多信息。不然,只需接受默認值便可,這幾乎老是正確的作法。數組
若是你接受默認的負載因數,但要指定初始容量,請選擇一個數字,該數字大約是你但願集合增加的大小的兩倍。若是你的猜想還遙遙無期,那麼你可能會浪費一些空間、時間或二者兼而有之,但這不太可能成爲一個大問題。安全
LinkedHashSet
與HashSet
具備相同的調整參數,可是迭代時間不受容量影響,TreeSet
沒有調整參數。數據結構
有兩個特殊用途的Set實現 — EnumSet和CopyOnWriteArraySet。oracle
EnumSet
是用於枚舉類型的高性能Set
實現,枚舉集的全部成員必須具備相同的枚舉類型,在內部,它由位向量表示,一般爲單個long
。枚舉集支持在枚舉類型範圍內進行迭代,例如,給定星期的枚舉聲明,你能夠在星期中進行迭代,EnumSet
類提供了一個易於使用的靜態工廠。函數
for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY)) System.out.println(d);
枚舉集還爲傳統的位標誌提供了豐富的類型安全替代。性能
EnumSet.of(Style.BOLD, Style.ITALIC)
CopyOnWriteArraySet
是由寫時複製數組備份的Set
實現。全部可變操做(例如add
、set
和remove
)都是經過製做數組的新副原本實現的,無需鎖定。甚至迭代也能夠安全地與元素插入和刪除同時進行,與大多數Set
實現不一樣,add
、remove
和contains
方法所需的時間與set
的大小成比例,此實現僅適用於不多修改但常常迭代的集合,它很是適合維護必須防止重複的事件處理列表。