一、前言
HashSet的基本特點是元素不可重複,但是不能保證元素的順序;同時也是不同步的,所以多線程常見會存在線程安全問題。在開發過程中,HashSet是一個不錯的去重工具。那是具體的實現機制是怎樣的呢?馬上開始揭曉。
二、源碼解讀
特性
HashSet繼承了集合框架AbstractSet<E>,保證了集合的基本特徵,實現了接口Set包含了基本集合操作,實現了接口Cloneable支持克隆,實現了Serializable支持序列化。
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
變量
//Set的實現原理
private transient HashMap<E,Object> map;
//集合中元素的映射值,不可變,所以所有元素的都是映射值相同
private static final Object PRESENT = new Object();
構造方法
五個構造方法,前四個都是用力構建單純哈希表,最後一個僅是構造函數由LinkedHashSet使用
//無參構造函數HashSet的實現機制就是HashMap
public HashSet() {
map = new HashMap<>();
}
//構造包含指定元素集合的set,map的初始化容量:最小爲16,最大等於加入集合大小的除0.75+1
//然後加集合加入到map中
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
//構造一個指定大小和負載係數的Set集合(map)
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
//構造一個指定大小Set,無負載系統
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
//構造函數僅由LinkedHashSet使用
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
主要方法
從下面的方法中,可以看出對Set集合操作實際上是對HashMap的操作,只是key不同,value相同。
//迭代
public Iterator<E> iterator() {
return map.keySet().iterator();
}
//集合大小
public int size() {
return map.size();
}
//判斷集合是否爲空
public boolean isEmpty() {
return map.isEmpty();
}
//集合是否包含某元素
public boolean contains(Object o) {
return map.containsKey(o);
}
//添加元素,實際只是添加key,value只是沒有含義的對象
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
//刪除元素,實際是更加key刪除元素
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
//清除元素
public void clear() {
map.clear();
}
//1.8新增的方法並行迭代
public Spliterator<E> spliterator() {
return new HashMap.KeySpliterator<E,Object>(map, 0, -1, 0, 0);
}
HashSet是如何實現元素不可重複的
通過源碼已知,Hash本質上就是HashMap,HashSet的元素實際上就是HashMap的key。最終要探究的其實是HashMap中的key爲什麼不能重複? 在通過查詢HashMap中的put的方法可以發現,在put元素時首先會計算key的hash值,通過hasn值來判斷元素加入的位置,同時會與已存在元素的hash比較,如果相等,繼續通過equas()比較hash值相同的兩個對象是否真的相同,如果仍然相同則不允許插入。
三、總結
HashSet的特點:
- 元素不可重複且無序,元素可爲null
- 非同步,不能線程安全
- 實現機制是HashMap
備註:JDK版本:1.8.0_241