Java 哈希码生成代码在计算中经常使用素数。这样做有充分的理由,如中所述为什么在 hashCode 中使用质数? https://stackoverflow.com/questions/3613102/why-use-a-prime-number-in-hashcode和其他地方。
例如,自动值 https://github.com/google/auto/tree/main/value将为给定值类生成以下哈希代码:
@Override
public int hashCode() {
int h = 1;
h *= 1000003;
h ^= this.firstName.hashCode();
h *= 1000003;
h ^= this.lastName.hashCode();
h *= 1000003;
h ^= this.age;
return h;
}
AutoValue 使用特定整数的原因是什么1000003
而不是其他素数?如果我使用 IntelliJ 创建一个覆盖的hashCode
方法,它使用整数31
。使用整数背后是否有一些逻辑和数学推理1000003
计算哈希码,而不是其他素数?谷歌搜索没有给我任何答案。
很想知道作者在想什么。
根据Google 内部提交 https://github.com/google/auto/discussions/1516#discussioncomment-5907729,选择 1000003 是因为一位前 Google 员工发现它的性能比 31 更好:
使用[另一个人]发现的哈希计算比*31+
当被问及此事时,AutoValue 开发人员 Kevin Bourrillion解释了可能选择该号码的原因 https://github.com/google/auto/discussions/1516#discussioncomment-5907978:
虽然我不记得细节了……这有点像我,以黄金比例的方式移动事物。尽管这可能会支持 898,459 的乘数,所以我想我也认为这对人眼来说应该是一个很好的简单数字。
但是,是的,让它变得更大的想法只是为了更快地吃掉所有这些初始零,并让这些位返回并相互干扰。
他还指出,较大的数字可以减少现实场景中发生哈希冲突的机会:
另外:(使用Integers
为简单起见)与List.of(a, b)
and List.of(c, d)
如果发生碰撞b - d
恰好是31次c - a
。与更大的乘数相比,想象现实世界中的情况可能会更容易一些。不过,这里没有确切的科学依据。Object.hashCode
无论如何,永远不会成为高质量的哈希函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)