Java的hashCode()方法是确定性的吗?

9

Java的hashCode()方法是确定性的吗?

我正在尝试实现一个使用minhashing算法的文档搜索引擎,我使用hashCode对单词进行预处理。 同样的单词每次运行时会获得相同的哈希值吗?

如果我从不同的机器上运行它(32位和64位),它是否会获得相同的哈希值?


1
我不会打赌这件事... 这甚至可能导致哈希与对象的地址相关联,然后它甚至可能在下一次运行时发生变化... - Basile Starynkevitch
请参阅https://dev59.com/C3I_5IYBdhLWcg3wHvU5。 - Annabelle
为什么不请朋友运行一小段代码样本并查看呢?为什么不发布该小段代码,以便我们所有人都可以执行它呢? :) 话虽如此,我不认为hashCode在多次运行之间是一致的,只适用于VM中的那个。 - Shark
为什么不使用像MD5这样的不同哈希算法呢? - SoWhat
你会用MD5进行哈希吗?也许对你来说很清楚,但我想为OP解释一下:像MD5这样的确定性转换无法扩展哈希空间的大小:如果你只有五个初始整数值,最终只会得到五个不同的MD5哈希(并增加内存使用)。 - Stefano Sanfilippo
答案是否定的。Object.hashCode()方法依赖于内存位置,这会随着JVM每次运行而改变。 - Eric Lindauer
3个回答

12
这取决于你所指的类。基础的Object.hashCode实现不是确定性的,因为正如文档中所述

尽可能合理地说,由Object类定义的hashCode方法确实会为不同的对象返回不同的整数。(通常通过将对象的内部地址转换为整数来实现,但这种实现技术并非JavaTM编程语言所必需的。)

地址是不确定的,有时甚至被用作熵的来源。
但是,例如,String具有确定性哈希码,如下所示:

Formula from Wikpedia

(图片来自维基百科)

在某些情况下,哈希码甚至没有一个合理的确定性定义。


+1 但是你应该使用Javadoc作为参考,而不是维基百科。请参考:http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#hashCode%28%29 - assylias
2
我只是说这个公式图像是从维基百科复制的,而不是我用它作为参考。已澄清。 - Stefano Sanfilippo

4

hashCode的一般契约如Javadoc所述:

在Java应用程序执行期间,如果同一对象被多次调用hashCode方法,则只要对象上用于equals比较的信息未修改,hashCode方法必须始终返回相同的整数。但是,该整数不需要在同一应用程序的另一个执行中保持一致。

每次运行相同的单词是否会得到相同的哈希值?

在应用程序执行期间,对等单词(我假设单词是String实例,并且在String中已重写equals())调用hashCode()应返回相同的整数。

编辑 由于javadoc中指定了如何计算String的哈希码,因此它是确定性的。

返回此字符串的哈希码。String对象的哈希码计算方式为: s[0]*31^(n-1) + s1*31^(n-2) + ... + s[n-1]

4
你的回答有些令人困惑。对于字符串来说,无论机器是32位还是64位,hashcode都是明确定义且确定性的。 - assylias
1
@assylias 是的,这实际上可能会成为DoS风险!攻击者可以构造一个HTTP请求,其中包含一堆字符串(环境变量和查询参数),旨在具有相同的哈希值,将近似O(1)的哈希映射有效地转换为O(N)的链表。嗷嗷。 - yshavit
3
注意,还有其他的类可以具有确定性哈希。例如,List 接口基于其元素定义其哈希值,因此如果所有元素都具有确定性哈希(例如,它们都是 String 类型),那么该列表也会具有确定性哈希。 - yshavit

3

说到总体的对象:它们不会。

但是如果你特别指的是String,那么hashcode的计算在String.hashCode()的API中有详细说明:

Returns a hash code for this string. The hash code for a String object is computed as

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

using int arithmetic, where s[i] is the ith character of the string, n is the length of the string, and ^ indicates exponentiation. (The hash value of the empty string is zero.)

换句话说:您应该可以依赖于字符串的hashCode稳定。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接