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

深度解析 Java hashCode() 與 equals() 契約及 HashSet 去重原理

     編輯:Java 相關知識

核心認知

  • hashCode() 返回 int 散列碼,決定對象在哈希表(HashMap/HashSet/Hashtable)中的存儲桶位置
  • 僅在哈希容器中生效,普通對象調用無實際意義
  • 契約:equals 相等 → hashCode 必相等;hashCode 相等 ↛ equals 必相等

HashSet 去重機制演示

錯誤示範:僅重寫 hashCode()

public class HashTest {
    private int i;
    public int hashCode() { return i % 10; }  // 故意製造碰撞
    // 未重寫 equals() → 使用 Object 默認引用比較
    
    public static void main(String[] args) {
        HashTest a = new HashTest(); a.setI(1);
        HashTest b = new HashTest(); b.setI(1);
        Set<HashTest> set = new HashSet<>();
        set.add(a); set.add(b);
        System.out.println(a.hashCode() == b.hashCode()); // true
        System.out.println(a.equals(b));                  // false
        System.out.println(set); // [HashTest@1, HashTest@1]  ← 重複對象!
    }
}

後果:同桶不同對象,HashSet 失去去重功能。

正確示範:同時重寫 hashCode() 與 equals()

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;
    HashTest other = (HashTest) obj;
    return this.i == other.i;  // 業務鍵一致即視為相等
}

@Override
public int hashCode() {
    return i % 10;  // 必須使用與 equals 相同的業務字段
}

結果:true true [HashTest@1] 僅保留一個對象。

最佳實踐總結

  1. 業務鍵一致性:hashCode 與 equals 必須基於相同業務字段計算
  2. 不可變性:參與計算的字段應為 final 或不可變,防止放入 Map 後修改導致找不到
  3. 分布均勻:優質 hashCode 應盡量分散,減少碰撞(可用 Objects.hash(field1, field2))
  4. IDEA 自動生成:Alt+Insert → equals() and hashCode() 可靠生成

常見誤區

「兩個對象 hashCode 相等就說明它們相等」→ 錯誤,只是落在同一桶,還需 equals 進一步比較。

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