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

问题

Java String的hashCode值计算为(String.hashCode()):

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

是否存在以下表达式将评估为false的任何情况(例如JVM版本,供应商等)?

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

更新#1:如果你声称答案是"是的,有这样的情况" - 那么请举一个具体的例子,说明"这是一个Java字符串".hashCode()!= 586653468。尝试具体/具体尽可能。

更新#2:我们都知道,依赖hashCode()的实现细节通常很糟糕。但是,我正在特别谈论String.hashCode() - 所以请将答案集中在String.hashCode()上。 Object.hashCode()在这个问题的上下文中完全不相关。


#1 热门回答(90 赞)

我可以看到早在Java 1.2中的文档。

虽然通常不应该依赖哈希码实现保持不变,但现在已经记录了java.lang.String的行为,因此更改它将被视为破坏现有合同。

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


#2 热门回答(18 赞)

我发现了一些关于JDK 1.0和1.1以及> = 1.2的内容:

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

有些不同,因为你似乎需要一个数字:如何使用CRC32或MD5代替哈希码,你很高兴 - 没有讨论也没有后顾之忧......


#3 热门回答(10 赞)

你不应该依赖哈希码等于特定值。只是它会在同一个执行中返回一致的结果。 API文档说如下:

hashCode的一般契约是:每当在Java应用程序的执行期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致。

编辑由于String.hashCode()的javadoc指定了如何计算String的哈希码,因此任何违反此规范的行都将违反公共API规范。