該類別
HashSet
實作接口Set
,基於哈希表,並由實例支援HashMap
。由於HashSet
元素沒有排序,因此不能保證在一段時間後元素的順序相同。只要雜湊函數正確地將元素分配到「桶」中,添加、刪除和搜尋操作就會在常數時間內完成,這將在後面討論。 關於以下幾個要點HashSet
:
- 因為 該類別實作了接口
Set
,它只能儲存唯一值; - 可以儲存NULL值;
- 元素添加的順序是使用哈希碼計算的;
HashSet
還實現了Serializable
和Cloneable
。
HashSet
成正比。因此,為了保持效能,重要的是不要將初始容量設定得太高(或負載因子太低)。初始容量 – 雜湊表中單元(“bin”)的初始數量。如果所有單元格都被填滿,它們的數量將自動增加。負載係數是衡量其容量自動增加之前的滿載程度的指標。當 中的元素數量大於初始容量和負載因子的乘積時,哈希表將被重新哈希(重新計算元素的哈希碼,並根據獲得的值重建表),並且數量其中的細胞數量增加了一倍。 負載因子 = 表中儲存的元素數量 / 雜湊表大小 例如,如果表中的初始單元格數量為 16,負載因子為 0.75,則當填充的單元格數量達到 12 時,細胞數量會自動增加。負載係數和初始容量是影響效能的兩個主要因素。0.75 的負載因子可提供良好的平均效能。如果增加該參數,那麼記憶體負載將會減少(因為它將減少重新散列和重建操作的次數),但會影響追加和查找操作。為了最大限度地減少重新散列所花費的時間,您需要選擇正確的初始容量參數。如果初始容量大於最大元素數除以負載因子,則根本不會發生重新雜湊操作。 HashSet
HashMap
HashSet
HashSet
HashSet
重要的:HashSet
不是具有內建同步功能的資料結構,因此如果多個執行緒同時對其進行操作,並且至少其中一個執行緒試圖進行更改,則有必要從外部提供同步存取。這通常是以另一個封裝HashSet
. 如果不存在這樣的對象,則Collections.synchronizedSet()
. 這是目前防止與HashSet
.
Set s = Collections.synchronizedSet(new HashSet(...));
哈希集構造函數:
HashSet h = new HashSet();
- 預設建構子。預設初始容量為16,負載係數為0.75。HashSet h = new HashSet(int initialCapacity)
– 具有給定初始容量的建構函式。負載係數 – 0.75。HashSet h = new HashSet(int initialCapacity, float loadFactor);
— 具有給定初始容量和負載係數的建構函數。HashSet h = new HashSet(Collection C)
– 新增另一個集合中的元素的建構子。
HashSet
:
import java.util.*;
class Test
{
public static void main(String[]args)
{
HashSet<String> h = new HashSet<String>();
// Add elements to the HashSet using the add() method
h.add("India");
h.add("Australia");
h.add("South Africa");
h.add("India");// try to add another same element
// Print the elements of the HashSet to the console
System.out.println(h);
System.out.println("List contains India or not:" +
h.contains("India"));
// Remove elements from the set using the remove() method
h.remove("Australia");
System.out.println("List after removing Australia:"+h);
// Loop through the elements of the HashSet using an iterator:
System.out.println("Iterating over list:");
Iterator<String> i = h.iterator();
while (i.hasNext())
System.out.println(i.next());
}
}
結論:
[South Africa, Australia, India]
List contains India or not:true
List after removing Australia:[South Africa, India]
Iterating over list:
South Africa
India
所有實作介面的類別Set
都由實作內部支援Map
。HashSet
使用 儲存元素HashMap
。儘管HashMap
元素必須表示為鍵值對才能新增元素,但 HashSet
僅會新增值。事實上,我們傳遞給物件的值HashSet
是物件的鍵HashMap
,並且使用一個常數作為值HashMap
。這樣,在每個鍵值對中,所有鍵都將具有相同的值。 實施HashSet
於java doc
:
private transient HashMap map;
// Constructor - 1
// All constructors implicitly create a HashMap object.
public HashSet()
{
// Create an implicit HashMap object
map = new HashMap();
}
// Constructor- 2
public HashSet(int initialCapacity)
{
// Create an implicit HashMap object
map = new HashMap(initialCapacity);
}
// An object of the Object class, each time acting as a value in the HashMap
private static final Object PRESENT = new Object();
如果你看一下方法add()
y HashSet
:
public boolean add(E e)
{
return map.put(e, PRESENT) == null;
}
您可以注意到方法add()
y呼叫內部物件上的HashSet
方法,將要新增的元素作為鍵傳遞給它,並將 PRESENT 常數作為值傳遞給它。該方法的工作原理類似。它呼叫內部物件方法: put()
HashMap
remove()
remove()
HashMap
public boolean remove(Object o)
{
return map.remove(o) == PRESENT;
}
HashSet
基於哈希表,新增、刪除或尋找操作平均將在常數 (O(1)) 時間內完成。 方法HashSet
:
boolean add(E e)
:在 中新增一個元素HashSet
,如果沒有,但如果這樣的元素已經存在,則該方法傳回false。void clear():
從集合中刪除所有元素。boolean contains(Object o)
:如果給定元素存在於集合中,則傳回true 。boolean remove(Object o)
:從集合中刪除給定元素(如果存在)。Iterator iterator()
:傳回集合元素的迭代器。boolean isEmpty()
:如果集合中沒有元素,則傳回true 。Object clone()
:執行表面克隆HashSet
。
GO TO FULL VERSION