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

Effective Java 實戰:高質量 hashCode() 通用實現模式

     編輯:Java 相關知識

前言

正確實現 hashCode() 是 Java 開發中的基本功,直接影響 HashMap、HashSet 等集合的性能與正確性。本文基於《Effective Java》經典規範,總結出一套通用、高質量的 hashCode() 實現模式,並提供完整代碼示例。

核心算法原則

  1. 初始化非零常數:int result = 17;(質數減少碰撞)
  2. 包含所有 equals() 比較字段:確保「相等對象哈希碼相等」契約
  3. 逐字段計算哈希碼並合併:result = 31 * result + fieldHash;(31 為質數,可優化為位運算)

各類型字段哈希碼計算規則

類型計算方式
boolean(f ? 1 : 0)
byte/char/short/int(int) f
long(int)(f ^ (f >>> 32))
floatFloat.floatToIntBits(f)
doubleDouble.doubleToLongBits(f) 轉 long 後按 long 處理
對象引用遞歸調用 hashCode();null 返回 0
數組各元素視為獨立字段處理;JDK 1.5+ 使用 Arrays.hashCode()

Arrays.hashCode(long[]) 參考實現

public static int hashCode(long a[]) {
    if (a == null) return 0;
    int result = 1;
    for (long element : a) {
        int elementHash = (int)(element ^ (element >>> 32));
        result = 31 * result + elementHash;
    }
    return result;
}

完整實戰示例:Person 類

package com.example.domain;

import java.util.Arrays;

public class Person {
    private int age;
    private String name;
    private char sex;
    private String[] hobbies;

    public Person(int age, char sex, String name, String[] hobbies) {
        this.age = age;
        this.sex = sex;
        this.name = name;
        this.hobbies = hobbies;
    }

    // Getter/Setter 省略...

    @Override
    public int hashCode() {
        int result = 1;
        result = 31 * result + age;
        result = 31 * result + sex;
        result = 31 * result + (name == null ? 0 : name.hashCode());
        if (hobbies != null) {
            for (String hobby : hobbies) {
                result = 31 * result + (hobby == null ? 0 : hobby.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
            && (name == null ? other.name == null : name.equals(other.name))
            && Arrays.equals(hobbies, other.hobbies);
    }
}

關鍵最佳實踐

  1. 始終覆寫 equals() 時同步覆寫 hashCode()
  2. 使用 JDK 提供的工具方法:Objects.hash() (JDK 7+)、Arrays.hashCode() 簡化實現
  3. 避免在 hashCode() 中包含可變字段:導致對象在集合中「丟失」
  4. 性能敏感場景可緩存哈希碼:不可變對象首次計算後緩存
  5. 不要試圖編寫「完美」哈希函數:31 乘法模式已足夠優秀

現代化簡化寫法(JDK 7+)

@Override
public int hashCode() {
    return Objects.hash(age, sex, name, Arrays.hashCode(hobbies));
}

總結

優質的 hashCode() 實現遵循:「質數種子 + 質數乘子 + 全字段覆蓋 + 空值安全 + 委託標準庫」。掌握此模式,配合 IDE 自動生成或 Lombok @EqualsAndHashCode,即可確保集合操作的正確性與高性能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved