【问题标题】:Could you explain the so called Java standard way to compute hashcode?你能解释一下所谓的 Java 标准计算哈希码的方法吗?
【发布时间】:2012-06-16 06:05:50
【问题描述】:

我最近不得不重写 Java 中的 equalshashCode 方法。因此,我寻找一种快速有效的方法来计算哈希码。

Java 开发人员似乎同意以下方法:

    int hash = 23;
    hash = hash * 37 + paramOne;
    hash = hash * 37 + paramTwo;
    // And so on...

这可能是简单的算术,但我真的不明白。有什么保证?什么是极端情况?有没有更好(相当简单)的方法呢?

谢谢!

【问题讨论】:

标签: java math hashcode


【解决方案1】:

用 Joshua Bloch 的话(解释 String 类中 hashCode() method 的默认实现,即:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]):

选择值 31 是因为它是一个奇数素数。如果它是偶数并且乘法溢出,则信息将丢失,因为乘以 2 相当于移位。使用素数的优势不太明显,但它是传统的。 31 的一个很好的特性是乘法可以用移位和减法代替以获得更好的性能:31 * i == (i

如需进一步阅读,请参阅thisthis

【讨论】:

    【解决方案2】:

    这是关于主要因素的。看看this answer

    如果您只是在寻找一种快速且实用的方法,并且您对性能没有重大顾虑,请查看 Apache Commons Lang HashCodeBuilder 或类似的库函数。 equals 有一个 equivalent builder

    【讨论】:

    • 我实际上尝试了几个版本的哈希码生成。使用标准硬编码31 * i<< N - 1,使用Objects.hashHashCodeBuilder,我发现HashCodeBuilder 的速度与Bloch 提到的标准硬编码速度大致相同(并且在内部它的作用相同计算)。我很惊讶,但我认为这与 JVM 通过在一定数量的初始调用后内联所有代码来优化代码有关。 Objects.hash 是最慢的之一,可能是由于 Object... objects 省略号参数中固有的幕后数组生成。
    【解决方案3】:

    Joshua Bloch 在他的“Effective Java”的第 3 章中告诉您如何正确地覆盖 equals 和 hashCode。谷歌搜索并阅读。

    他是集合 API 的编写者,现在是 Google 的首席 Java 架构师。这对我来说已经足够权威了。

    【讨论】:

    • 不是?我想应该是现在
    • 哦,天哪。谢谢你指出我的错误。早上太早,在黑暗中打字。
    猜你喜欢
    • 1970-01-01
    • 2012-01-11
    • 2016-01-19
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    相关资源
    最近更新 更多