Java 两个不同长度的字符串可以有相同的哈希代码吗?
虽然我知道两个不同的字符串可以返回相同的哈希代码,但我一直找不到关于两个不同长度的字符串返回相同哈希代码的任何信息。这是否可能,如果可能,请举例说明。这是使用java hashcode函数,以防更改任何内容。Hashcodes分布在Java 两个不同长度的字符串可以有相同的哈希代码吗?,java,string,hashcode,Java,String,Hashcode,虽然我知道两个不同的字符串可以返回相同的哈希代码,但我一直找不到关于两个不同长度的字符串返回相同哈希代码的任何信息。这是否可能,如果可能,请举例说明。这是使用java hashcode函数,以防更改任何内容。Hashcodes分布在int的空间中。对于int,只有2^32=~40亿可能的值。可能存在的字符串远不止这些,因此根据鸽子洞原理,必须存在多个具有相同哈希代码的字符串 但是,这并不能证明不同长度的字符串可能具有相同的哈希代码,如下所述。Java使用的公式是s[0]*31^(n-1)+s[1
int
的空间中。对于int
,只有2^32=~40亿
可能的值。可能存在的字符串远不止这些,因此根据鸽子洞原理,必须存在多个具有相同哈希代码的字符串
但是,这并不能证明不同长度的字符串可能具有相同的哈希代码,如下所述。Java使用的公式是s[0]*31^(n-1)+s[1]*31^(n-2)+…+s[n-1]
用于哈希字符串。知道了这一点,很容易构造具有相同哈希代码的不同长度的字符串:
让字符串s1=“\001!”代码>和字符串s2=“@”代码>。然后s1.length()!=s2.length()
但s1.hashCode()='\001'*31+'!'==1*31+33==64==s2.hashCode()=='@'==64
然而,让我再次指出,int
的可能值超过40亿,因此碰撞概率很低,尽管没有您想象的那么低,因为,这使得在大约77K散列之后,碰撞概率约为50%(假设散列是随机分布的,这实际上取决于您的数据-如果您主要处理长度非常小的字符串,则冲突会更频繁)。但是,使用散列处理的每个数据结构都必须处理冲突(例如,一种常见的方法是在每个散列位置使用链表),或者处理数据丢失(例如,在布卢姆过滤器中)。是的,这可能发生
一些相当琐碎的例子:
- 初始零值字符不会影响哈希代码,因此(例如)
“foo”
、“\0foo”
、“\0\0foo”
”等都具有相同的哈希代码
- 在添加下一个字符之前,每个字符只需乘以31;因此(例如)两个字符的字符串<代码>新字符串(新字符[]{12,13})
与单个字符<代码>新字符串(新字符[]{12*31+13})具有相同的哈希代码
(其中我任意选择了12
和13
;只要12*31+13
模拟值保持在两字节无符号整数范围内,任何其他值都可以使用相同的方法)
但这些只是一些易于构造的示例。也有许多字符串对碰巧具有相同的哈希代码,尽管它们之间没有明显的关系。可能相关/有用:这并不回答长度是否重要。例如,如果哈希代码类似于某个函数(字符串)