java 字符串上的 hashCode() 的一致性

2022-08-31 07:51:07

Java 字符串的哈希值计算如下 (String.hashCode()):

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

是否有任何情况(例如 JVM 版本、供应商等)以下表达式的计算结果为 false?

boolean expression = "This is a Java string".hashCode() == 586653468

更新 #1:如果你声称答案是“是的,有这种情况” - 那么请给出一个具体的例子,当“这是一个Java字符串”.hashCode() != 586653468。尽量具体/具体。

更新 #2:我们都知道,依赖hashCode()的实现细节通常是不好的。但是,我专门谈论的是String.hashCode() - 所以请把答案集中在String.hashCode()上。Object.hashCode() 在这个问题的上下文中是完全无关紧要的。


答案 1

我可以看到这个文档早在Java 1.2。

虽然一般来说,你不应该依赖哈希代码实现保持不变,但它现在记录了的行为,所以改变它会被视为破坏现有的契约。java.lang.String

只要有可能,你不应该依赖哈希代码在版本等之间保持不变 - 但在我看来是一个特例,因为算法已被指定......当然,只要您愿意在指定算法之前放弃与版本的兼容性。java.lang.String


答案 2

我发现了一些关于JDK 1.0和1.1的东西,>= 1.2:

在 JDK 1.0.x 和 1.1.x 中,长字符串的 hashCode 函数通过对第 n 个字符进行采样来工作。这可以很好地保证您将有许多字符串散列到相同的值,从而减慢哈希表查找速度。在 JDK 1.2 中,该函数已得到改进,将到目前为止的结果乘以 31,然后按顺序添加下一个字符。这有点慢,但在避免碰撞方面要好得多。资料来源:http://mindprod.com/jgloss/hashcode.html

不同的东西,因为你似乎需要一个数字:使用CRC32或MD5而不是哈希码怎么样,你很好 - 没有讨论,也不用担心......