我想知道在 java 中编写 #hashCode() 方法的最佳实践是什么。
可以找到很好的描述here。有那么好吗?
这是引用自有效的Java第二版,第 9 项:“始终覆盖hashCode
当你覆盖equals
":
虽然本项中的配方产生了相当好的散列函数,但它并没有产生最先进的散列函数,Java 平台库也没有提供从 1.6 版开始的此类散列函数。编写这样的哈希函数是一个研究课题,最好留给数学家和计算机科学家。 [...尽管如此,]本项中描述的技术对于大多数应用来说应该足够了。
乔什·布洛赫的食谱
- 将一些常量非零值(例如 17)存储在
int
变量称为result
- Compute an
int
hashcode c
for each field f
that defines 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
1.5 版本中添加的方法
- 合并哈希码
c
into 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 开始,有一个方便的 varargs 变体java.util.Objects.hash(Object...).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)