7

最近出现了一个有趣的问题。我们遇到了一些hashCode()用作 MD5 加密的盐源的代码,但这提出了一个问题:hashCode()在不同的 VM、不同的 JDK 版本和操作系统上是否会为相同的对象返回相同的值?即使不能保证,到现在为止它有没有改变?

编辑:我的意思是String.hashCode()而不是更一般Object.hashCode()的,当然可以被覆盖。

4

5 回答 5

9

没有。来自http://tecfa.unige.ch/guides/java/langspec-1.0/javalang.doc1.html

hashCode 的一般合约如下:

  • 每当在 Java 应用程序执行期间对同一对象多次调用它时,hashCode 必须始终返回相同的整数。整数可以是正数、负数或零。然而,这个整数不必从一个 Java 应用程序到另一个 Java 应用程序,或从一个应用程序的一次执行到同一应用程序的另一次执行保持一致。[...]
于 2008-10-10T07:14:19.773 回答
4

这取决于类型:

  • 如果你有一个没有覆盖 hashCode() 的类型,那么每次运行程序时它可能会返回不同的 hashCode()。
  • 如果你有一个覆盖 hashCode() 的类型但没有记录它是如何计算的,那么对于具有相同数据的对象在每次运行时返回不同的哈希值是完全合法的,只要它为重复返回相同的哈希值在同一次运行中调用。
  • 如果您有一个以记录方式覆盖 hashCode() 的类型,即算法是记录行为的一部分,那么您可能是安全的。(例如,java.lang.String 记录了这一点。)但是,我个人仍然避免在一般原则上依赖它。

只是来自 .NET 世界的一个警示故事:我已经看到至少有几个人因为使用 string.GetHashCode() 的结果作为他们在数据库中的密码散列而感到痛苦。该算法在 .NET 1.1 和 2.0 之间发生了变化,突然间所有的哈希值都“错误”了。(Jeffrey Richter 通过 C# 在 CLR 中记录了几乎相同的情况。)当确实需要存储哈希时,我希望它以始终保证稳定的方式计算 - 例如 MD5 或由您的类型具有稳定性的保证。

于 2008-10-10T08:02:33.873 回答
3

根据文档: String 对象的哈希码计算为

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

我不确定这是一个正式的规范还是只是 Sun 的实现。至少,在所有现有的 Sun VM 上,它应该是相同的,无论平台或操作系统如何。

于 2008-10-10T15:24:23.500 回答
1

不可以。除非另有说明,否则不保证哈希算法。因此例如,哈希结构的反序列化需要重新计算哈希码,而这些值不应该以序列化的形式存储。

于 2008-10-10T08:08:13.610 回答
0

我想补充一点,您可以覆盖 hashCode()(如果这样做,请不要忘记 equals())以确保您的业务对象在任何地方都返回相同的 hashCode。然后,这些对象将至少具有可预测的 hashCode。

于 2008-10-10T07:38:31.020 回答