Set 特徵:無序、不可重複。HashSet 底層基於哈希表(HashMap)實現,元素按 hashCode() 分桶,equals() 判斷相等。
class Demo { }
Demo d1 = new Demo(), d2 = new Demo();
System.out.println(d1); // Demo@1a8fa0f0
System.out.println(d2); // Demo@4b8efa2f
HashSet<Demo> set = new HashSet<>();
set.add(d1); set.add(d2);
System.out.println(set); // [Demo@4b8efa2f, Demo@1a8fa0f0] 順序不可預期
未重寫 hashCode/equals 時,默認按對象地址計算哈希碼,兩對象視為不同,均可入集合。
class Demo {
@Override public int hashCode() { return 90; } // 固定哈希碼
@Override public boolean equals(Object obj) {
System.out.println("調用 equals 判斷相等");
return super.equals(obj); // 默認比較地址
}
}
// 輸出:
// Demo@5a
// Demo@5a
// 調用 equals 判斷相等
// [Demo@5a, Demo@5a]
哈希碼相同 → 進入同一桶 → 呼叫 equals() 比較 → 地址不同 → 判定為不同元素 → 以鏈表/紅黑樹形式順延存儲。
a.equals(b) == true,則 a.hashCode() == b.hashCode() 必須成立;hashCode() 相等不代表 equals() 相等(哈希碰撞);Set 元素或 Map 鍵的類,必須同時重寫 兩方法,保持一致性。理解此機制,可避免「明明相等卻存入兩份」或「本應不同卻被視為重複」的低級錯誤。