根據 Object 規範,重寫 equals() 時必須重寫 hashCode(),以滿足:
obj1.equals(obj2) == true,則 obj1.hashCode() == obj2.hashCode() 必為 true。obj1.hashCode() != obj2.hashCode(),則 obj1.equals(obj2) 必為 false(逆否命題)。違反契約會導致 HashSet、HashMap、Hashtable 等雜湊容器行為異常(如重複元素無法去重)。
equals() 用於值比較(預設比較引用地址)。hashCode() 用於雜湊桶定位,加速查找。hashCode 定位桶,再用 equals 精確比對。若兩物件 equals 相等但 hashCode 不同,會落入不同桶,導致容器誤判為不同物件。class Name implements Serializable {
private String id;
public Name(String id) { this.id = id; }
@Override public boolean equals(Object obj) {
if (obj instanceof Name) {
Name other = (Name) obj;
return id.equals(other.id);
}
return false;
}
@Override public int hashCode() {
return id.hashCode(); // 委派給 String 的 hashCode
}
}
Name n1 = new Name("01");
Name n2 = new Name("01");
Set<Name> set = new HashSet<>();
set.add(n1);
set.add(n2);
System.out.println(set.size()); // 輸出 1,符合預期
System.out.println(n1.equals(n2)); // true
System.out.println(n1.hashCode() == n2.hashCode()); // true
equals 不重寫 hashCode:導致 HashSet 存入重複物件。hashCode 計算欄位與 equals 比較欄位不一致:違反契約。hashCode:物件放入容器後修改欄位,導致找不到原桶位置。Objects.hash(field1, field2, ...) (Java 7+) 自動生成穩定雜湊碼。equals/hashCode 時,確保欄位集合一致。hashCode 優化效能。equals 與 hashCode 是雙生契約,缺一不可。正確實作是使用雜湊容器的前提。