關於HashMap的源碼解讀,可參考https://blog.csdn.net/jiang_zf/article/details/104532186
一、一些變量介紹
//用來存儲元素,從這裏也可以看出來,hashset內部是以hashmap實現的
private transient HashMap<E,Object> map;
//定義一個常量,在向map存儲時的所有值都是用這個常量代替
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
二、構造函數
1.
//默認初始化一個HashMap對象
public HashSet() {
map = new HashMap<>();
}
2.
//可指定大小和負載比,但實際還是初始化一個hashmap對象
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
3.
//可指定容量大小,但初始化的還是hashmap對象
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
4.
//這次初始化的是一個linkedhashmap對象,可以看出最後一個參數暫時沒用,但是有這個參數,就可以初始化爲linkedhashmap對象
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
5.
//這個構造函數允許傳入集合進行初始化
public HashSet(Collection<? extends E> c) {
//直接通過集合大小和默認負載比推算出應該初始化的容量,+1是爲了防止出現小數向上取整
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
//添加元素
addAll(c);
}
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;//這一行我感覺沒有太多意義,只要最後一個插入成功就是返回true,有知道的告訴我一下是不是有別的用
return modified;
}
三、添加方法--add
//可見內部還是調用的hashmap的put方法實現,我們知道HashMap的put方法如果該位置已經存在一個一樣的Key,會用新的value替換原來的舊的value,並且返回舊的value,所以對於HashSet而言第一次插入返回null就代表成功,以後再次插入同樣的元素,返回的是一個對象,表示已經存在這樣的元素了,插入失敗
public boolean add(E e) {
return map.put(e, PRESENT)==null;//這裏可以看出爲什麼插入的默認值不能爲null,因爲爲null的話,put之後返回的也爲null,不能知道是插入了新的還是返回了老的null值
}
四、 刪除方法--remove
//也是調用的hashmap的移除方法,同添加一樣,通過返回的值判斷是否刪除成功
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}