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

HashSet 源碼級淺析:哈希去重、無序性驗證與性能特徵

     編輯:Java 綜合教學

HashSet 源碼級淺析:哈希去重、無序性驗證與性能特徵

核心特性速覽

特性說明
底層結構HashMap,value 統一 PRESENT 常量
去重機制hashCode() 定桶 → equals() 精確比較
順序性無序,迭代順序不保證,隨擴容變化
Null 支援允許 1 個 null 元素
線程安全非線程安全,併發用 Collections.synchronizedSet 或 ConcurrentHashMap.newKeySet()
序列化/克隆實現 Serializable、Cloneable

關鍵源碼片段

public class HashSet extends AbstractSet implements Set, Cloneable, Serializable {
    private transient HashMap map;
    private static final Object PRESENT = new Object();
    
    public HashSet() { map = new HashMap<>(); }
    
    public boolean add(E e) { return map.put(e, PRESENT) == null; }
    public boolean contains(Object o) { return map.containsKey(o); }
    public boolean remove(Object o) { return map.remove(o) == PRESENT; }
    public Iterator iterator() { return map.keySet().iterator(); }
    // ...
}

實戰驗證:去重與無序

1. 元素不可重複

Set set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
set.add(3); // 重複,不添加
set.add("string");
int[] arr1 = {7,8,9};
int[] arr2 = arr1; // 同一引用
set.add(arr1);
set.add(arr2); // 同引用,不重複
set.add("中文");
set.add("中文也不可重複");
set.add("中文也不可重複"); // 重複字符串

// 輸出:1 - 2 - 3 - string - [I@hash - 中文 - 中文也不可重複 -

2. 元素無順序(十萬元素驗證)

Set set = new HashSet<>();
for (int i = 1; i <= 100000; i++) set.add(i);

int disorderCount = 0;
Integer prev = null;
for (Integer curr : set) {
    if (prev != null && curr < prev) disorderCount++;
    prev = curr;
}
System.out.println("無序確認: " + (disorderCount > 0) + ", 逆序對數: " + disorderCount);
// 輸出:無序確認: true, 逆序對數: 17232 (多次運行穩定)

結論:HashSet 迭代順序由哈希桶分佈決定,非插入順序,非自然順序,不可依賴順序。

性能特徵分析

擴容機制

  • 默認負載因子 0.75,閾值 = capacity * 0.75
  • 擴容為 2 倍(冪次方),重新計算所有元素 hash 分桶
  • 大數據量預估初始容量:new HashSet<>(expectedSize / 0.75f + 1)

常見誤區與最佳實踐

  1. 存放可變對象:加入 Set 後修改字段導致 hashCode 改變 → 無法查找/刪除 → 不可變對象或不修改影響 hash/equals 的字段
  2. 未重寫 hashCode/equals:默認 Object 身份比較 → 邏輯相等對象被視為不同 → 值類型必須重寫
  3. 併發環境直接使用:導致數據不一致、死循環 → 用 ConcurrentHashMap.newKeySet() 或 CopyOnWriteArraySet
  4. 依賴迭代順序:業務邏輯假設插入順序 → 改用 LinkedHashSet 保持插入順序

對比:HashSet vs LinkedHashSet vs TreeSet

操作平均時間最壞情況說明
add/contains/removeO(1)O(n)哈希衝突退化為鏈表/紅黑樹
遍歷O(n)O(n)遍歷 HashMap Entry 數組 + 鏈表
特性HashSetLinkedHashSetTreeSet
底層HashMapLinkedHashMapTreeMap (紅黑樹)
順序無序插入順序自然順序/Comparator
性能最快 O(1)略慢 O(1)O(log n)
Null允許 1 個允許 1 個不允許 (NPE)

總結

HashSet 以極致的 O(1) 增刪查換取順序不可預期。理解其HashMap 委託實現、hashCode/equals 雙重去重、負載因子擴容機制,能幫助你在去重、標籤系統、ID 集合等高頻場景做正確選型與調優。

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