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

Java 集合核心:hashCode() 與 equals() 契約深度解析與最佳實踐

     編輯:Java 綜合教學

hashCode() 存在的意義

Java 集合分兩大派:

  • List:有序、可重複,靠索引定位
  • Set:無序、不可重複

Set 如何高效去重?遍歷調用 equals() 成本 O(n)。hashCode() 提供「分桶」機制:

  1. 調用 hashCode() 計算哈希值
  2. 映射到數組索引:index = (hash & 0x7FFFFFFF) % table.length
  3. 桶為空 → 直接存入
  4. 桶非空 → 僅對桶內元素調用 equals() 比較

大幅減少 equals() 調用次數,提升插入/查找性能至接近 O(1)。

hashCode() 設計權衡

策略優點缺點
所有屬性參與分佈均勻,衝突極低計算開銷大,影響性能
少數關鍵屬性計算快衝突率高,退化為鏈表查找

工程妥協: 緩存哈希值,屬性變更時重新計算(如 String、BigInteger)。

HashMap 索引計算與沖突處理

int index = (hash & 0x7FFFFFFF) % tab.length;
  • & 0x7FFFFFFF:確保正數(哈希值可能為負)
  • 沖突不可避免(鴿巢原理:數據量 > 2^32 必有衝突)
  • 鍵值對設計:key 保存原對象,equals() 精確判斷同一性

hashCode() 與 equals() 契約(鐵律)

equals() 五大規則

  1. 自反性:x.equals(x) == true
  2. 對稱性:x.equals(y) == y.equals(x)
  3. 傳遞性:x.equals(y) && y.equals(z) → x.equals(z)
  4. 一致性:多次調用結果不變
  5. 非空性:x.equals(null) == false

hashCode() 契約

  1. 相等必同碼: x.equals(y) == true → x.hashCode() == y.hashCode()
  2. 不等碼可同: x.equals(y) == false → hashCode() 可能相等也可能不等

判斷流程圖解

hashCode-equals 判斷流程

  1. 比較 hashCode():不等 → 判定不等,結束
  2. 相等 → 比較 equals():不等 → 判定不等;相等 → 判定相等

實戰範例:Person 類正確實現

public class Person {
    private int age;
    private int sex; // 0男 1女
    private String name;
    private final int PRIME = 37;

    @Override
    public int hashCode() {
        int result = 1;
        result = (result + Integer.hashCode(age) + Integer.hashCode(sex)) * PRIME;
        result = PRIME * result + (name == null ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person other = (Person) obj;
        return age == other.age && sex == other.sex 
            && Objects.equals(name, other.name);
    }
}

驗證測試

Set set = new HashSet<>();
set.add(new Person(11, 1, "張三")); // p1
set.add(new Person(12, 1, "李四")); // p2
set.add(new Person(11, 1, "張三")); // p3 同 p1
set.add(new Person(11, 1, "李四")); // p4
// 結果:set.size() == 3(p1/p3 視為同一元素)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved