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

Java equals() 與 hashCode() 契約深度解析與最佳實踐

     編輯:Java 綜合教學

Java equals() 與 hashCode() 契約深度解析與最佳實踐

1. Object 基礎契約

  • equals(Object):默認比較引用地址(this == obj)。
  • hashCode():native 方法,通常基於對象地址生成。
  • 核心規約:equals(true) ⇒ hashCode() 必相等;hashCode() 相等 ⇏ equals(true)。

2. 為什麼要重寫?

集合框架(HashSet、HashMap、Hashtable)依賴雙重校驗:

  1. 先比 hashCode() 定位桶(O(1))。
  2. 桶內再逐個 equals() 精確匹配。

若僅重寫 equals() 不重寫 hashCode(),邏輯相等對象可能落入不同桶,導致 Set 重複、Map 查不到。

3. 標準重寫範本

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return id == person.id && Objects.equals(name, person.name);
}

@Override
public int hashCode() {
    return Objects.hash(id, name); // JDK 7+ 推薦
    // 手寫版:31 * id + (name == null ? 0 : name.hashCode());
}

4. 常見陷阱案例

場景現象原因
String s1=new("a"), s2=new("a")s1==s2 false,s1.equals(s2) trueString 重寫 equals 比內容,hashCode 同算法
自定義類未重寫 hashCodeHashSet 添加兩個邏輯相等對象均保留繼承 Object.hashCode() 基於地址,落入不同桶
hashCode 常量返回 1所有對象進同一桶,退化為鏈表 O(n)滿足契約但效能極差

5. 集合存儲判等流程圖解

add(element)
   │
   ├─► hashCode() → 定位桶
   │
   ├─► 桶為空 → 直接存入 ✓
   │
   └─► 桶非空 → 遍歷桶內 Entry
            │
            ├─► hashCode() 不等 → 繼續下一個
            │
            └─► hashCode() 相等 → equals() 比較
                     │
                     ├─► true  → 視為重複,不存入 / 覆蓋 value
                     │
                     └─► false → 繼續下一個

6. Hibernate/JPA 實體類特殊要求

  • 實體類 必須 重寫雙方法,建議基於業務主鍵(而非數據庫生成 ID,因暫存態 ID 為 null)。
  • 集合映射(Set、Map key)極其依賴契約正確性。

7. 總結口訣

「equals 比業務鍵,hashCode 同算法;
兩方法必須同增減,緩存哈希慎重寫。」

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