若
a.equals(b) == true,則a.hashCode() == b.hashCode()必須成立。
反之不要求:hashCode 相等不代表 equals 相等(哈希碰撞)。
public class HashCodeDemo {
public static void main(String[] args) {
String s1 = "aaa";
String s2 = s1; // 同一引用
String s3 = "bbb"; // 不同內容
System.out.println(s1.equals(s2)); // true
System.out.println("s1.hashCode() = " + s1.hashCode()); // 96321
System.out.println("s2.hashCode() = " + s2.hashCode()); // 96321
System.out.println("s3.hashCode() = " + s3.hashCode()); // 97314
}
}
true
s1.hashCode() = 96321
s2.hashCode() = 96321
s3.hashCode() = 97314
s1 與 s2 指向同一對象,equals 為 true,hashCode 當然相同。s3 內容不同,hashCode 也不同(極小概率碰撞除外)。equals() 時 必須 重寫 hashCode(),否則作為 HashMap Key 或 HashSet 元素會出現「明明放進去了卻取不出」的 Bug。equals/hashCode 時,會基於相同字段計算,保證契約。String 的 hashCode() 算法:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],JDK 內部緩存結果(hash 字段),二次調用極快。// 錯誤:只重寫 equals,不重寫 hashCode
class BadKey {
String id;
@Override public boolean equals(Object o) {
return o instanceof BadKey && id.equals(((BadKey)o).id);
}
// 缺少 hashCode() → 繼承 Object.hashCode()(基於內存地址)
}
// 結果:new BadKey("1") 和 new BadKey("1") 放入 HashMap 會被視為不同 Key