Java類集框架 —— HashSet、LinkedHashSet源碼分析

前言

HashSet實現(xiàn)了Set接口,它的底層是由HashMap來支持的。HashSet的元素實際上是存儲在底層HashMapkey上的。由于HashMap的無序不重復特性,HashSet存儲的元素也是無序的,并且元素也不能重復,同時也只允許存儲一個null元素。

HashSet源碼分析

主要屬性:

// HashSet底層map
private transient HashMap<E,Object> map;
// 虛擬對象
private static final Object PRESENT = new Object();

HashSet是通過HashMap來保存元素,由于只需要在key中保存,所以采用虛擬對象PRESENT對應map中插入key-valuevalue值的引用。每次向map中添加元素時,鍵值對對應的value都是PRESENT。

構造函數:

// 默認無參構造
public HashSet() {
    map = new HashMap<>();
}
// 根據已有集合元素來構造HashSet
public HashSet(Collection<? extends E> c) {
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    addAll(c);
}
// 給定初始容量
public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
}
// 給定初始容量和加載因子
public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<>(initialCapacity, loadFactor);
}
// 這個構造函數外部不能調用,供LinkedHashSet復寫
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

構造函數都是初始map,以便加入元素的時候存儲。

重要方法:

// 集合大小
public int size() {
    return map.size();
}

// 集合是否為空
public boolean isEmpty() {
    return map.isEmpty();
}

// 添加元素
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

// 移除元素
public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
}

// 清空集合
public void clear() {
    map.clear();
}

// 集合中是否有元素o
public boolean contains(Object o) {
    return map.containsKey(o);
}

HashSet的增刪改查,同時直接操作map來完成的,代碼都非常簡單。

LinkedHashSet

LinkedHashSet繼承自HashSet,它的構造方法:

public LinkedHashSet() {
    super(16, .75f, true);
}

public LinkedHashSet(int initialCapacity) {
    super(initialCapacity, .75f, true);
}

public LinkedHashSet(int initialCapacity, float loadFactor) {
    super(initialCapacity, loadFactor, true);
}

public LinkedHashSet(Collection<? extends E> c) {
    super(Math.max(2*c.size(), 11), .75f, true);
    addAll(c);
}

LinkedHashSet構造方法調用了父類HashSet的這個構造方法:

// LinkedHashSet復寫,初始化LinkedHashMap
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

所以,它的底層是一個LinkedHashMap,元素的所有操作都是由LinkedHashMap來維護。LinkedHashSetHashSet的區(qū)別和LinkedHashMapHashMap的區(qū)別一樣,LinkedHashMapLinkedHashSet是有序的,內部由雙向鏈表來記錄順序,而HashMapHashSet都是無序的。

最后

對于HashSet/LinkedHashSet,只要閱讀過HashMap/LinkedHashMap的源碼,基本上就能完全了解它的實現(xiàn)原理。HashSet/LinkedHashSet中數據的存入、刪除、訪問都是都是直接操作內部的HashMap,可以說HashSet/LinkedHashSet是在HashMap/LinkedHashMap的基礎上加了一層殼。他們唯一的區(qū)別就是HashSet/LinkedHashSet保存的元素時單個的數據或對象,而HashMap/LinkedHashMap保存的元素時鍵值對。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容