HashSet原始碼淺析
引言
HashSet 實現set介面,繼承AbstractSet類;是一個不允許儲存重複元素的集合;
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
HashSet類兩個主要屬性
成員變數map修飾符為transient:hashset也定製了序列化方法;針對transient 修飾的欄位
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
可以看出
- HashSet內部是由hashMap實現的;
- PRESENT :是所有寫入 map 的 value 值。
add
呼叫map的put方法,寫入<K,V> = <e,PRESENT>
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
可以看出它是將存放的物件當做了 HashMap 的健,value 都是相同的 PRESENT 。由於 HashMap 的 key 是不能重複的,所以每當有重複的值寫入到 HashSet 時,value 會被覆蓋,但 key 不會受到影響,這樣就保證了 HashSet 中只能存放不重複的元素。
如果指定的元素尚不存在,則將其新增到此集合中。如果此集合不包含元素e2(e == null?e2 == null:e.equals(e2)),則將指定元素e新增到此集合。 如果此set已包含該元素,則呼叫將保持set不變並返回false。
contains
類似的hashset是否contains一個元素,呼叫的是map.containsKey(o)
方法:map是否包含該key
public boolean contains(Object o) {
return map.containsKey(o);
}
remove
如果存在,則從該集合中移除指定的元素。 更正式的,如果此集合包含這樣的元素,則刪除元素e(o == null?e == null:o.equals(e))。 如果此set包含該元素,則返回true(或等效地,如果此set由於呼叫而更改)。 (一旦呼叫返回,該集合將不包含該元素。)
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
序列化
…
官方說明
This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time. This class permits the null element.
允許null元素
This class offers constant time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets. Iterating over this set requires time proportional to the sum of the HashSet instance’s size (the number of elements) plus the “capacity” of the backing HashMap instance (the number of buckets). Thus, it’s very important not to set the initial capacity too high (or the load factor too low) if iteration performance is important.
基本操作的時間複雜度都為O(1),常數時間
Note that this implementation is not synchronized. If multiple threads access a hash set concurrently, and at least one of the threads modifies the set, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the set. If no such object exists, the set should be “wrapped” using the Collections.synchronizedSet method. This is best done at creation time, to prevent accidental unsynchronized access to the set:
同樣是執行緒不安全的,轉換成執行緒安全,可以使用Collections.synchronizedSet()包裝一下
Set s = Collections.synchronizedSet(new HashSet(...));
The iterators returned by this class’s iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator’s own remove method, the Iterator throws a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
fail-fast機制,ConcurrentModificationException