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

Java 重寫 equals() 必須重寫 hashCode():契約與實戰詳解

     編輯:Java 相關知識

核心契約

根據 Object 規範,重寫 equals() 時必須重寫 hashCode(),以滿足:

  1. 若 obj1.equals(obj2) == true,則 obj1.hashCode() == obj2.hashCode() 必為 true。
  2. 若 obj1.hashCode() != obj2.hashCode(),則 obj1.equals(obj2) 必為 false(逆否命題)。

違反契約會導致 HashSet、HashMap、Hashtable 等雜湊容器行為異常(如重複元素無法去重)。

為什麼需要 hashCode?

  • equals() 用於值比較(預設比較引用地址)。
  • hashCode() 用於雜湊桶定位,加速查找。
  • 雜湊容器先比 hashCode 定位桶,再用 equals 精確比對。若兩物件 equals 相等但 hashCode 不同,會落入不同桶,導致容器誤判為不同物件。

實戰範例

class Name implements Serializable {
    private String id;
    public Name(String id) { this.id = id; }

    @Override public boolean equals(Object obj) {
        if (obj instanceof Name) {
            Name other = (Name) obj;
            return id.equals(other.id);
        }
        return false;
    }

    @Override public int hashCode() {
        return id.hashCode(); // 委派給 String 的 hashCode
    }
}

驗證程式碼

Name n1 = new Name("01");
Name n2 = new Name("01");
Set<Name> set = new HashSet<>();
set.add(n1);
set.add(n2);
System.out.println(set.size()); // 輸出 1,符合預期
System.out.println(n1.equals(n2)); // true
System.out.println(n1.hashCode() == n2.hashCode()); // true

常見錯誤

  • 只重寫 equals 不重寫 hashCode:導致 HashSet 存入重複物件。
  • hashCode 計算欄位與 equals 比較欄位不一致:違反契約。
  • 使用可變欄位計算 hashCode:物件放入容器後修改欄位,導致找不到原桶位置。

最佳實踐

  1. 使用 Objects.hash(field1, field2, ...) (Java 7+) 自動生成穩定雜湊碼。
  2. IDE 自動生成 equals/hashCode 時,確保欄位集合一致。
  3. 不可變物件適用緩存 hashCode 優化效能。

總結

equals 與 hashCode 是雙生契約,缺一不可。正確實作是使用雜湊容器的前提。

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