HashMap 判斷鍵相等依賴 hashCode() 定位桶位 + equals() 精確比較。自定義對象作 Key 時,必須同時重寫 這兩個方法,否則會出現「邏輯相等但 HashMap 視為不同鍵」的嚴重 Bug。
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 記錄,值分別為「上海」和「鐵嶺」,去重失效。
@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 大小正確。
a.equals(b) 為 true,則 a.hashCode() == b.hashCode() 必須為 true。hashCode() 相等不要求 equals() 相等(允許哈希碰撞)。Objects.hash(...) (JDK7+) 或 IDE 自動生成,保持字段一致性。同樣適用於 HashSet、HashMap Key、ConcurrentHashMap Key 等基於哈希的集合。