高效的 hashCode() 实现

Posted

技术标签:

【中文标题】高效的 hashCode() 实现【英文标题】:Efficient hashCode() implementation 【发布时间】:2010-11-07 15:41:51 【问题描述】:

我经常使用 IntelliJ IDEA 自动生成一个类的 hashCode() 方法,该方法通常采用以下形式:

result = 31 * result + ...

我的问题是乘以 31 的目的是什么?我知道这是一个质数,但为什么要专门选择 31?此外,如果为特别小/大的数据集实现hashCode(),人们会以不同的方式解决这个问题吗?

【问题讨论】:

【参考方案1】:

乘以 31 很快,因为 JIT 可以将其转换为左移 5 位和减法:

x * 31 == (x << 5) - x

如果没有任何特别的额外信息,我会坚持这种方法。它的速度相当快,并且很可能最终得到分布合理的哈希码,而且它也很容易正确:)

数据集的大小并不重要,但如果您有关于您将使用的值的特定额外信息(例如“它总是偶数”),那么您也许能够设计一个更好的哈希函数。不过,我会等到这是一个实际问题:)

【讨论】:

那为什么不是 7?这是一个 3 的移位和一个减法。这是一个素数 谢谢乔恩。如果这是原因,那么奇怪的是 IDEA 不只是将 (x 7 允许仅在两个相邻字符上不同的字符串通常以相同的哈希码结束。事实上,过去一两年的几乎任何处理器都应该能够在一个周期内管理一个八位数的乘法(只要它在寄存器中)。 上次我检查 31 也是素数。 @dma_k:恐怕我不知道它的细节......只是它的目的是为了很好地工作。 (我认为 Effective Java 实际上建议了 31 个……也许是第二版这样做了?)

以上是关于高效的 hashCode() 实现的主要内容,如果未能解决你的问题,请参考以下文章

高效 告别996,开启java高效编程之门 3-26去重

干货,使用布隆过滤器实现高效缓存!

关于hashcode 里面 使用31 系数的问题

整数 hashCode 的最佳实现是啥?

集合的 hashCode 方法的最佳实现

如何正确实现 Java 中的 HashCode