两个不同长度的字符串可以具有相同的哈希码吗?
Can two strings of different length have the same hashcode?
虽然我知道两个不同的字符串可以 return 相同的哈希码,但我一直找不到关于两个不同长度的字符串的信息。这是否可能,如果可以,将不胜感激。这是使用 java 哈希码函数,以防发生任何变化。
哈希码分布在 int
的 space 上。 int
只有 2^32 = ~4 billion
个可能的值。可能的字符串远不止这个数量,因此根据鸽巢原理,必须存在多个具有相同哈希码的字符串。
但是,这并不能证明不同长度的字符串可能具有相同的哈希码,如下所述。 Java 使用公式 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
对字符串进行哈希处理。知道了这一点,构造具有相同哈希码的不同长度的字符串就很容易了:
让String s1 = "[=14=]1!";
和String s2 = "@";
。然后 s1.length() != s2.length()
但 s1.hashCode() == '[=17=]1' * 31 + '!' == 1 * 31 + 33 == 64 == s2.hashCode() == '@' == 64
。
但是,让我再说一遍,int
有超过 4 亿 个可能值,所以你的碰撞概率很低,虽然没有低到你可能会想,因为 Birthday Paradox,这让你在大约 77K 哈希后有大约 50% 的机会发生冲突(假设哈希是随机分布的,这实际上取决于你的数据 - 如果你主要处理非常小长度的字符串,你会更频繁地发生冲突)。但是,每个使用散列处理的数据结构都必须处理冲突(例如,一种常见的方法是在每个散列位置使用链表),或者处理数据丢失(例如,在布隆过滤器中)。
是的,这可能会发生。
一些相当简单的例子:
- 初始零值字符不影响散列码,因此(例如)
"foo"
、"[=11=]foo"
、"[=12=][=12=]foo"
等都具有相同的散列-code.
- 在添加下一个字符之前,每个字符只乘以 31;所以(例如)双字符字符串
new String(new char[] { 12, 13 })
与单字符 new String(new char[] { 12 * 31 + 13 })
具有相同的哈希码(我在其中任意选择了 12
和 13
;相同适用于任何其他值,只要 12 * 31 + 13
模拟保持在双字节无符号整数范围内)。
但这些只是一些易于构建的示例。还有很多字符串对恰好具有相同的哈希码,尽管它们之间没有明显的关系。
虽然我知道两个不同的字符串可以 return 相同的哈希码,但我一直找不到关于两个不同长度的字符串的信息。这是否可能,如果可以,将不胜感激。这是使用 java 哈希码函数,以防发生任何变化。
哈希码分布在 int
的 space 上。 int
只有 2^32 = ~4 billion
个可能的值。可能的字符串远不止这个数量,因此根据鸽巢原理,必须存在多个具有相同哈希码的字符串。
但是,这并不能证明不同长度的字符串可能具有相同的哈希码,如下所述。 Java 使用公式 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
对字符串进行哈希处理。知道了这一点,构造具有相同哈希码的不同长度的字符串就很容易了:
让String s1 = "[=14=]1!";
和String s2 = "@";
。然后 s1.length() != s2.length()
但 s1.hashCode() == '[=17=]1' * 31 + '!' == 1 * 31 + 33 == 64 == s2.hashCode() == '@' == 64
。
但是,让我再说一遍,int
有超过 4 亿 个可能值,所以你的碰撞概率很低,虽然没有低到你可能会想,因为 Birthday Paradox,这让你在大约 77K 哈希后有大约 50% 的机会发生冲突(假设哈希是随机分布的,这实际上取决于你的数据 - 如果你主要处理非常小长度的字符串,你会更频繁地发生冲突)。但是,每个使用散列处理的数据结构都必须处理冲突(例如,一种常见的方法是在每个散列位置使用链表),或者处理数据丢失(例如,在布隆过滤器中)。
是的,这可能会发生。
一些相当简单的例子:
- 初始零值字符不影响散列码,因此(例如)
"foo"
、"[=11=]foo"
、"[=12=][=12=]foo"
等都具有相同的散列-code. - 在添加下一个字符之前,每个字符只乘以 31;所以(例如)双字符字符串
new String(new char[] { 12, 13 })
与单字符new String(new char[] { 12 * 31 + 13 })
具有相同的哈希码(我在其中任意选择了12
和13
;相同适用于任何其他值,只要12 * 31 + 13
模拟保持在双字节无符号整数范围内)。
但这些只是一些易于构建的示例。还有很多字符串对恰好具有相同的哈希码,尽管它们之间没有明显的关系。