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

Java hashCode() 與 equals() 契約深度解析:Hash 集合正確性的基石

     編輯:Java 綜合教學

核心契約:不可違反的鐵律

若兩物件 equals() 回傳 true,則其 hashCode() 必須相等。

反向不要求:hashCode 相等不代表 equals 為真 (哈希碰撞)。

預設實作

  • Object.hashCode():通常為記憶體地址映射 (Native 實作)
  • Object.equals():比較記憶體地址 (即 ==)

為什麼 Hash 集合依賴此契約?

HashMap/HashSet 內部維護哈希桶陣列:

  1. 計算 Key 的 hashCode() → 定位桶索引
  2. 桶內以 equals() 逐一比對

違反契約後果:

  • equals()=true 但 hashCode() 不等 → 物件落入不同桶 → 查找/刪除失效、記憶體洩漏、重複元素

正確重寫範例

public class User {
    private Long id;
    private String name;
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) && Objects.equals(name, user.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id, name); // JDK 7+ 推薦
        // 手寫: 31 * (id != null ? id.hashCode() : 0) + (name != null ? name.hashCode() : 0)
    }
}

最佳實踐清單

  1. 重寫 equals 必重寫 hashCode
  2. 使用相同欄位集合計算兩者
  3. 欄位含集合/陣列時需深度比對
  4. 優先用 Objects.equals/hash (空值安全)
  5. 不可變物件可緩存 hashCode (如 String)
  6. 不要在 equals/hashCode 使用非最終/可變欄位

常見誤區

誤區後果
只重寫 equalsHash 集合失效
hashCode 用隨機數/時間同一物件多次調用不等,集合找不到自己
equals 比較 hashCode邏輯循環、效能差
業務 Key 用可變物件修改欄位後導致 Map 找不到原 Key

效能小貼士

  • 高頻 Key 類別:預計算 hashCode 緩存 (不可變物件)
  • 避免過度複雜的 hashCode 計算 (影響放入/查找速度)
  • IDE 自動生成通常足夠,人工微調僅針對熱點類
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved