特點
實現了Set接口
HashSet依賴的數據結構是HashMap
因爲實現的是Set接口,所以不允許有重複的值
插入到HashSet中的對象不保證與插入的順序保持一致。對象的插入是根據它的hashcode
HashSet中允許有NULL值
HashSet也實現了Searlizable和Cloneable兩個接口
初始化尺寸就是當創建哈希表(HashSet內部用哈希表的數據結構)的時候桶(buckets)的數量。如果當前的尺寸已經滿了,那麼桶的數量會自動增長
裝載因子衡量的是在HashSet自動增長之前允許有多滿。當哈希表中實體的數量已經超出裝載因子與當前容量的積,那麼哈希表就會再次進行哈希(也就是內部數據結構重建),這樣哈希表大致有兩倍桶的數量。
如果內部容量爲16,裝載因子爲0.75,那麼當表中有12個元素的時候,桶的數量就會自動增長。
裝載因子和初始化容量是影響HashSet操作的兩個主要因素。裝載因子爲0.75的時候可以提供關於時間和空間複雜度方面更有效的性能。如果我們加大這個裝載因子,那麼內存的上限就會減小(因爲它減少了內部重建的操作),但是將影響哈希表中的add與查詢的操作。爲了減少再哈希操作,我們應該選擇一個合適的初始化大小。如果初始化容量大於實體的最大數量除以裝載因子,那麼就不會有再哈希的動作發生了。
這個類實現了一個哈希表支持的Set接口實現,實際上是一個HashMap
它不能保證集合的迭代順序,特別不能保證隨着時間的推移,秩序將保持不變。
這個類允許null值
此類爲基本操作提供恆定的時間性能(add、remove、contains、size).
假設hash函數在桶之間正確地分散元素,在這個集合上迭代需要時間,與HashSet實例大小的和加上HashMap實例支持的capacity(bucket桶的數量)成比例。
因此不設置初始容量太高或者load factor太低是非常重要的 如果迭代性能是重要的,如果迭代性能是重要的。
同步
注意此實現不同步,如果多個線程同時訪問哈希集,則至少有一個線程修改集合,它必須外部同步。這通常是通過對某些對象進行同步來實現的。自然封裝該集合。
如果不存在這樣的對象,則應該使用wrapped {@link Collections#synchronizedSet Collections.synchronizedSet}方法。最好在創建時完成,以防止意外發生。
Set s = Collections.synchronizedSet(new HashSet(...));
迭代器由class的iterator 是fail-fast 如果這個set可修改的 在任何時候 在迭代器創建之後,如果迭代器在任何時候修改了集合,除了通過迭代器自己的remove方法,
迭代器將會拋出{@link ConcurrentModificationException}.
因此,面對併發修改,iterator 快速而乾淨失敗,而不是在未來時間 不確定的 冒險的行爲 。
注意,迭代器的故障快速行爲不能得到保證,事實上,一般來說,不可能作出任何硬的保證,存在不同步的併發修改。故障快速迭代器在盡力的基礎上拋出ConcurrentModificationException、
*因此,編寫一個依賴於此異常正確性的程序是錯誤的。迭代器的fail-fast行爲只用於檢測缺陷。
/**
* 如果此set中尚未包含指定元素,則添加指定元素。
* 更確切地講,如果此 set 沒有包含滿足(e==null ? e2==null : e.equals(e2))
* 的元素e2,則向此set 添加指定的元素e。
* 如果此set已包含該元素,則該調用不更改set並返回false。
*
* 底層實際將將該元素作爲key放入HashMap。
* 由於HashMap的put()方法添加key-value對時,當新放入HashMap的Entry中key
* 與集合中原有Entry的key相同(hashCode()返回值相等,通過equals比較也返回true),
* 新添加的Entry的value會將覆蓋原來Entry的value,但key不會有任何改變,
* 因此如果向HashSet中添加一個已經存在的元素時,新添加的集合元素將不會被放入HashMap中,
* 原來的元素也不會有任何改變,這也就滿足了Set中元素不重複的特性。
* @param e 將添加到此set中的元素。
* @return 如果此set尚未包含指定元素,則返回true。
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
// 定義一個虛擬的Object對象作爲HashMap的value,將此對象定義爲static final。
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();