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

【Java每日一題】20170104:HashSet 存儲自定義對象時 hashCode 與 equals 契約驗證

     編輯:Java 綜合教學

【Java每日一題】20170104:HashSet 存儲自定義對象時 hashCode 與 equals 契約驗證

題目來源:微信公眾號「weknow619」。

代碼

package Jan2017;
import java.util.HashSet;
import java.util.Set;

public class Ques0104 {
    public static void main(String[] args) {
        Obj obj01 = new Obj("張三");
        Obj obj02 = new Obj("李四");
        Obj obj03 = new Obj("李四");

        Set set = new HashSet<>();
        set.add(obj01);
        set.add(obj02);
        set.add(obj03);

        System.out.println(set.size());
    }
}

class Obj {
    private String id;
    public Obj(String id) { this.id = id; }

    @Override public int hashCode() { return 123; } // 固定返回值

    @Override public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj instanceof Obj && this.id.equals(((Obj) obj).id)) return true;
        return false;
    }
}

輸出結果

2

解析

  1. hashCode() 恆返回 123,導致所有對象落入同一哈希桶,HashSet 退化為鏈表/紅黑樹查找。
  2. 添加 obj01("張三"):桶為空,直接插入 → size=1。
  3. 添加 obj02("李四"):同桶,遍歷調用 equals,與 obj01 比較 id 不同 → 插入 → size=2。
  4. 添加 obj03("李四"):同桶,先比較 obj01 (id不同) → 再比較 obj02 (id相同) → equals 返回 true → 判定重複,不插入 → size 仍為 2。

核心契約

「如果兩個對象 equals() 返回 true,則它們的 hashCode() 必須相等。」
反向不要求:hashCode 相等不代表 equals 為真(哈希碰撞)。

最佳實踐

  • 重寫 equals 必須重寫 hashCode,且包含相同字段。
  • 使用 IDE 自動生成或 Objects.hash(field1, field2...) (JDK 7+)。
  • 不可變對象適合緩存 hashCode;可變對象字段參與 hashCode 需謹慎(放入 Set/Map 後不可修改相關字段)。
  • 測試類應覆蓋:相等對象 hashCode 相等、不相等對象盡量分散、null 安全。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved