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

HashMap 存儲自定義對象鍵的關鍵:必須重寫 hashCode() 與 equals() 方法

     編輯:Java 綜合教學

HashMap Key 正確性契約:hashCode 與 equals 一致性

HashMap 判斷鍵相等依賴 hashCode() 定位桶位 + equals() 精確比較。自定義對象作 Key 時,必須同時重寫 這兩個方法,否則會出現「邏輯相等但 HashMap 視為不同鍵」的嚴重 Bug。

反例:未重寫 hashCode/equals

public class Student {
    private String name; private int age;
    // 構造器、getter/setter 省略
    // 未重寫 hashCode/equals
}

HashMap<Student, String> hm = new HashMap<>();
hm.put(new Student("lisi", 38), "北京");
hm.put(new Student("zhaoliu", 24), "上海");
hm.put(new Student("xiaoqiang", 31), "瀋陽");
hm.put(new Student("wangcai", 38), "大連");
hm.put(new Student("zhaoliu", 24), "鐵嶺"); // 邏輯相同對象,但 hashCode 不同

// 遍歷輸出
for (Student k : hm.keySet())
    System.out.println(k.getName() + ":" + k.getAge() + "--" + hm.get(k));

輸出:

輸出結果

出現兩條 zhaoliu:24 記錄,值分別為「上海」和「鐵嶺」,去重失效。

正例:重寫 hashCode 與 equals

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

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

重寫後,邏輯相同的 Student("zhaoliu",24) 將映射到同一桶位並通過 equals 判定相等,後 put 覆蓋前值,Map 大小正確。

核心契約

  1. 若 a.equals(b) 為 true,則 a.hashCode() == b.hashCode() 必須為 true。
  2. hashCode() 相等不要求 equals() 相等(允許哈希碰撞)。
  3. 重寫時建議使用 Objects.hash(...) (JDK7+) 或 IDE 自動生成,保持字段一致性。

同樣適用於 HashSet、HashMap Key、ConcurrentHashMap Key 等基於哈希的集合。

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