在java中编写哈希函数的最佳实践是什么?

Den*_* S. 38 java hash

我想知道在java中编写#hashCode()方法的最佳实践是什么.很好的描述可以在这里找到.这样好吗?

pol*_*nts 54

Here's a quote from Effective Java 2nd Edition, Item 9: "Always override hashCode when you override equals":

虽然这个项目中的配方产生了相当好的散列函数,但它不会产生最先进的散列函数,Java平台库也不提供1.6版本的散列函数.编写这样的哈希函数是一个研究课题,最好留给数学家和计算机科学家.[...尽管如此,]此项目中描述的技术应该适用于大多数应用程序.

Josh Bloch的食谱

  • 在一个int名为的变量中存储一些常量非零值,比如17result
  • 计算定义的每个字段的int哈希码: cfequals
    • 如果该字段是a boolean,则计算(f ? 1 : 0)
    • 如果该字段是a byte, char, short, int,则计算(int) f
    • 如果该字段是a long,则计算(int) (f ^ (f >>> 32))
    • 如果该字段是a float,则计算Float.floatToIntBits(f)
    • 如果该字段是a double,则计算Double.doubleToLongBits(f),然后long如上所述对结果进行散列
    • 如果该字段是一个对象引用,并且该类的equals方法通过递归调用来比较该字段equals,则hashCode在该字段上递归调用.如果该字段的值为null,则返回0
    • 如果该字段是数组,则将其视为每个元素都是单独的字段.如果数组字段中的每个元素都很重要,则可以使用Arrays.hashCode版本1.5中添加的方法之一
  • 将哈希码组合cresult如下:result = 31 * result + c;

现在,当然,这个配方相当复杂,但幸运的是,你不必每次都重新实现它,多亏了java.util.Arrays.hashCode(Object[]).

@Override public int hashCode() {
    return Arrays.hashCode(new Object[] {
           myInt,    //auto-boxed
           myDouble, //auto-boxed
           myString,
    });
}
Run Code Online (Sandbox Code Playgroud)

从Java 7开始,有一个方便的varargs变体java.util.Objects.hash(Object...).


Ces*_*sar 23

hashCode()" 有效Java "一书中描述了实现的一个很好的参考.在了解了生成良好哈希函数背后的理论之后,您可以从Apache commons lang中检查HashCodeBuilder,它实现了本书中描述的内容.来自文档:

这个类可以为任何类构建一个好的hashCode方法.它遵循Joshua Bloch撰写的Effective Java一书中规定的规则.编写好的hashCode方法实际上非常困难.本课程旨在简化流程.