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

Java 理論與實踐:正確實現 equals() 與 hashCode() 契約

     編輯:Java 程式設計入門

核心契約:equals 與 hashCode 的不可分關係

所有 Java 對象繼承 Object 的兩個方法:

  • equals(Object obj):判斷邏輯相等性。
  • hashCode():返回哈希碼,供 HashMap、HashSet 等基於哈希的容器高效存取。

鐵律: 若覆寫 equals(),必須覆寫 hashCode()。契約要求:a.equals(b) == true ⇒ a.hashCode() == b.hashCode()。反向不要求(允許哈希碰撞)。

默認實現與值類語義

  • 默認 equals(): 引用相等 (this == obj)。
  • 默認 hashCode(): 從內存地址衍生(可能碰撞)。
  • 值類 (Integer、String、包裝類): 覆寫為內容相等。Integer.equals() 比較 intValue();String.equals() 比較字符序列。這使它們可作為可靠的 Map Key。

為什麼必須覆寫?

若 Integer 不覆寫,作為 HashMap Key 時,get() 必須使用與 put() 完全相同的對象實例才能命中,極不實用且易錯。覆寫後,語義相等的不同實例均可正確存取。

equals() 必須滿足的數學屬性

  1. 自反性: x.equals(x) == true (x ≠ null)
  2. 對稱性: x.equals(y) ⇔ y.equals(x)
  3. 傳遞性: x.equals(y) && y.equals(z) ⇒ x.equals(z)
  4. 一致性: 多次調用結果不變,除非比較依賴的字段被修改。
  5. 非空性: x.equals(null) == false
  6. 與 hashCode 一致: 相等對象哈希碼必相等。

實現指南與最佳實踐

1. 只有不可變類適合作為 Map Key

可變對象作 Key 會導致修改字段後哈希碼變化,在 Map 中「找不到自己」。String、包裝類、BigInteger、LocalDate 等不可變類是完美 Key。

2. 標準實現模板

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    MyClass that = (MyClass) o;
    return Objects.equals(field1, that.field1) &&
           Objects.equals(field2, that.field2) &&
           Double.compare(that.field3, field3) == 0; // 浮點數比較
}

@Override
public int hashCode() {
    return Objects.hash(field1, field2, field3);
}
  • 使用 Objects.equals() 安全處理 null。
  • 使用 Objects.hash() 自動組合哈希碼(Java 7+)。
  • 浮點數用 Double.compare / Float.compare 避免 NaN、-0.0 陷阱。
  • 僅包含參與 equals() 比較的字段,保持一致性。

3. 避免常見陷阱

  • 參數類型寫成 MyClass 而非 Object → 重載而非覆寫,破壞多態。
  • 忘記檢查 null 或 getClass() → 拋出 NPE 或違反對稱性。
  • 在可變類中基於可變字段實現 → 作 Key 時極其危險。
  • 為了性能簡化 hashCode()(如只用一個字段) → 嚴重哈希碰撞,退化為鏈表 O(n)。

總結

正確實現 equals()/hashCode() 是 Java 開發基本功。遵循契約、使用 Objects 輔助類、堅持不可變性、覆蓋所有相關字段,能讓你的類在集合框架中表現可靠、高效。

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