我想知道在java中编写#hashCode()方法的最佳实践是什么。 可以找到好的描述here。这样好吗?
答案 0 :(得分:52)
以下是来自 Effective Java 2nd Edition 的引用,第9项:“覆盖hashCode
时始终覆盖equals
”:
虽然这个项目中的配方产生了相当好的散列函数,但它不会产生最先进的散列函数,Java平台库也不提供1.6版本的散列函数。编写这样的哈希函数是一个研究课题,最好留给数学家和计算机科学家。 [...尽管如此,]此项目中描述的技术应该适用于大多数应用程序。
int
result
变量中存储一些常量非零值,例如17
int
的每个字段c
计算f
哈希码equals
:
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
,则返回0 Arrays.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...)
中有一个方便的varargs变体。
答案 1 :(得分:21)
hashCode()
一书中介绍了{{1}}实施的绝佳参考。在了解了生成良好哈希函数背后的理论之后,您可以从Apache commons lang中检查Effective Java,它实现了本书中描述的内容。来自文档:
这个类启用了一个好的hashCode 为任何类构建的方法。它 遵循书中规定的规则 约书亚布洛赫的有效Java。 编写一个好的hashCode方法是 实际上相当困难。这个班 旨在简化流程。
答案 2 :(得分:0)
正如@leonbloy所说,好好理解它。然而,即便如此,一个“最佳”的做法是简单地让IDE为您编写功能。在某些情况下它不会是最佳的 - 在一些非常罕见的情况下它甚至都不会好 - 但在大多数情况下,它很容易,可重复,没有错误,并且像它需要一样好(作为哈希码)成为。当然,阅读文档并理解它 - 但不要不必要地使它复杂化。