我想知道在Java中编写#hashCode()方法的最佳实践是什么。 可以在这里找到一个好的描述。它是否很好?
我想知道在Java中编写#hashCode()方法的最佳实践是什么。 可以在这里找到一个好的描述。它是否很好?
以下是来自《Effective Java第二版》第9项的引用:“当你重写equals方法时,总是要重写hashCode方法”:
虽然本条目中的配方可以产生相当不错的哈希函数,但它并不能产生最先进的哈希函数,而且截至1.6版本,Java平台库也没有提供这样的哈希函数。编写这样的哈希函数是一个研究课题,最好由数学家和计算机科学家来完成。[...尽管如此,]本条目中描述的技术对于大多数应用程序来说应该是足够的。
result
的int
变量中存储一些常数非零值,比如17。equals
的每个字段f
计算一个int
哈希码c
:
boolean
类型,则计算(f ? 1 : 0)
byte, char, short, int
类型,则计算(int) f
long
类型,则计算(int) (f ^ (f >>> 32))
float
类型,则计算Float.floatToIntBits(f)
double
类型,则先计算Double.doubleToLongBits(f)
,然后像上面那样哈希结果的long
equals
方法通过递归调用equals
来比较该字段,则对该字段递归调用hashCode
。如果该字段的值为null
,则返回0Arrays.hashCode
方法之一。c
组合到result
中,如下所示: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,
});
}
从Java 7开始,java.util.Objects.hash(Object...)
提供了一个方便的可变参数变体。
hashCode()
的很好的参考资料可以在书籍Effective Java中找到。当你理解了生成良好哈希函数的理论之后,可以查看Apache commons lang提供的HashCodeBuilder,该类实现了书中所述的内容。从文档中可以看出:
该类使得可以为任何类构建一个好的hashCode方法。它遵循Joshua Bloch在书籍Effective Java中制定的规则。编写一个好的hashCode方法实际上相当困难。此类旨在简化该过程。
正如@leonbloy所说,理解它很重要。即便如此,一个“最佳”实践是让你的IDE为你编写函数。在某些情况下,它可能不是最优的 - 在极少数情况下甚至可能不好 - 但对于大多数情况而言,它易于操作、可重复、无误差,并且足够好(就像哈希码一样)。当然,阅读文档并充分理解它 - 但不要不必要地使它变得复杂。