在 Java 集合框架中,List 和 Set 是兩大核心體系。List 允許元素重複且有序,而 Set 則強調元素唯一性且無序。當我們向 Set 添加元素時,必須判斷該元素是否已存在。若單純依賴 equals() 逐一比對,當集合擁有 1000 個元素時,第 1001 個元素需調用 1000 次 equals(),效率極低。
Java 引入哈希表(Hash Table)機制。hashCode() 返回對象的哈希碼,可理解為對象在內存中的「物理地址標識」(實際非真實地址)。新增元素時,先計算 hashCode() 定位存儲位置:
equals() 比較這將比較次數從 O(n) 降至 O(1) 量級,極大提升性能。
Java 規範強制要求:
a.equals(b) == true,則 a.hashCode() == b.hashCode() 必須成立a.hashCode() == b.hashCode(),a.equals(b) 可能為 true 也可能為 false(哈希碰撞)違反規約會導致 HashSet、HashMap 等集合出現重複元素或查找失效。
| 維度 | equals() | hashCode() |
|---|---|---|
| 調用者 | 業務代碼主動調用 | 集合框架內部調用 |
| 用途 | 判斷邏輯相等(內容一致) | 快速定位存儲桶位置 |
| 返回值 | boolean | int |
以學生對象為例,若認定「姓名+性別相同即相等」:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student s = (Student) o;
return Objects.equals(name, s.name) && gender == s.gender;
}
@Override
public int hashCode() {
return Objects.hash(name, gender); // 組合相同字段的哈希碼
}
關鍵原則:參與 equals 比較的字段,必須參與 hashCode 計算,確保邏輯一致性。
equals() 不重寫 hashCode() → 集合失效return 42;) → 退化為鏈表,性能崩潰掌握 hashCode() 與 equals() 的協作機制,是高效使用 Java 集合、避免難以排查 Bug 的基石。