为什么@AutoValue注解使用特定的整数1000003来计算哈希码?

Why @AutoValue annotation uses the specific integer 1000003 for calculating hash code?

提问人:ARK 提问时间:6/28/2018 最后编辑:M. JustinARK 更新时间:5/16/2023 访问量:214

问:

Java 哈希代码生成代码在其计算中通常使用质数。这是有充分理由的,如为什么在hashCode中使用质数?和其他地方所解释的那样。

例如,AutoValue 将为给定的值类生成以下哈希代码:

@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 使用特定整数而不是其他质数的原因是什么?如果我使用 IntelliJ 创建一个重写的方法,它使用 integer .使用整数而不是其他质数来计算哈希码背后是否有一些逻辑和数学推理?谷歌搜索没有给我任何答案。1000003hashCode311000003

很想知道作者在想什么。

java 等于 哈希码 相等 自动值

评论

1赞 6/28/2018
我很确定 10^6+3 是一个素数,这使得哈希冲突发生的可能性低于合数。
2赞 tune5ths 6/28/2018
正如@AJC所提到的,需要一个质数来避免哈希冲突。我的猜测是,有人可能出于任意的原因决定“使用超过一百万的第一个质数”。知道是否有更深层次的原因会很有趣。
1赞 Joachim Sauer 5/16/2023
@M.Justin:“为什么选择这个”的问题在SO上是出了名的难做,因为除非设计师自己出现,否则它们往往没有“正确”的答案。我的建议是直接联系代码的作者,询问是否有人能记住选择该号码的具体原因。
1赞 Joachim Sauer 5/16/2023
没错,我自己也遇到过几次这个问题,通常只是停止与这个问题互动;-)无关紧要,我很好奇自动值的历史是否暗示了这个问题的答案,但似乎这个项目的所有公共历史都已经包含了那个神奇的常数:github.com/google/auto/commit/......
1赞 M. Justin 5/16/2023
@JoachimSauer 您的建议已被采纳,作者已被询问,并给出了解释:github.com/google/auto/discussions/1516。Kevin Bourrillion:“使用[另一个人]发现的哈希计算,其性能远远优于”;[...]我不记得细节了 [...] 把事情转移到黄金比例的一小部分上。[...]我想我也认为这对人眼来说应该是一个不错的简单数字。[...]让它变大的想法只是为了更快地吃掉所有这些初始零,并让这些位回来并相互干扰。*31+

答:

1赞 M. Justin 5/16/2023 #1

根据 Google 内部提交,之所以选择 1000003,是因为一位前 Google 员工发现它的性能优于 31:

使用 [另一个人] 发现的哈希计算的性能远远优于*31+

当被问及这个问题时,AutoValue 开发人员 Kevin Bourrillion 解释了可能选择该号码的原因

虽然我不记得细节了......这有点像我,把事情转移到黄金比例的分数上。虽然这可能会使乘数达到 898,459,但我想我也认为这对人眼来说应该是一个不错的简单数字。

但是,是的,让它变大的想法只是为了更快地吃掉所有这些初始零,并让这些位回来并相互干扰。

他还指出,在实际场景中,较大的数字会降低哈希冲突的几率:

另外:(为简单起见)与,如果碰巧是 31 次,你会得到碰撞。而且,想象现实世界的情况可能比使用更大的乘数要容易一些。不过,这里没有确切的科学。 无论如何,它永远不会完全是一个高质量的哈希函数。IntegersList.of(a, b)List.of(c, d)b - dc - aObject.hashCode