首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

HashSet 深度解析:JDK 源碼視角下的集合實現原理

     編輯:Java 綜合教學

HashSet 的核心設計理念

在探討 HashMap 時,我們已了解「Hash」代表散列、「Map」代表映射。那麼 Set 又是什麼?從詞源上看,Set 對應數學中的「集合」概念——元素不可重複。因此 HashSet 的本質就是:以散列表(Hash Table)為底層結構,維護一個無重複元素的集合。

類結構與核心字段

public class HashSet<E> extends AbstractSet<E> 
    implements Set<E>, Cloneable, java.io.Serializable

HashSet 繼承 AbstractSet,實現 Set、Cloneable 與 Serializable 接口。其核心存儲容器是一個 transient HashMap<E, Object> map,鍵存放集合元素,值統一使用一個靜態常量:

private static final Object PRESENT = new Object();

這個佔位對象 PRESENT 是實現「鍵唯一、值無意義」的關鍵。

五種構造函數詳解

1. 無參構造

public HashSet() { map = new HashMap<>(); }

2. 集合轉換構造

public HashSet(Collection<? extends E> c) {
    map = new HashMap<>(Math.max((int)(c.size()/.75f) + 1, 16));
    addAll(c);
}

初始容量取 集合大小/0.75 + 1 與 16 的較大值,避免頻繁擴容,兼顧空間效率。

3. 指定容量與負載因子

public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<>(initialCapacity, loadFactor);
}

4. 僅指定初始容量

public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
}

5. 內部構造(給 LinkedHashSet 使用)

HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

第三個參數 dummy 僅為區分重載,實際未使用;底層改用 LinkedHashMap 以保持插入順序。

核心方法實現機制

方法實現邏輯關鍵點
iterator()map.keySet().iterator()遍歷鍵集合
size()map.size()委託 Map
isEmpty()map.isEmpty()委託 Map
contains(o)map.containsKey(o)判斷鍵是否存在
add(e)map.put(e, PRESENT) == null首次放入返回 null,表示添加成功
remove(o)map.remove(o) == PRESENT刪除鍵並比對值是否為佔位對象
clear()map.clear()清空底層 Map

克隆與序列化

淺克隆

public Object clone() {
    HashSet<E> newSet = (HashSet<E>) super.clone();
    newSet.map = (HashMap<E, Object>) map.clone(); // 僅克隆 Map 結構,元素共享
    return newSet;
}

自定義序列化

僅序列化 鍵(元素),值 PRESENT 固定不需存儲。反序列化時根據 instanceof LinkedHashSet 決定重建 HashMap 或 LinkedHashMap。

Java 8 新增:Spliterator

public Spliterator<E> spliterator() {
    return new HashMap.KeySpliterator<>(map, 0, -1, 0, 0);
}

Spliterator(可分割迭代器)支援並行遍歷,將元素分批交由多線程處理,提升大數據集吞吐量。

總結

HashSet 實際上是對 HashMap 的一層薄封裝:將元素作為 Key,固定對象作為 Value,從而以「映射」實現「集合」的數學語義。理解這一點,便能貫通其所有操作的本質。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved