虽然我知道两个不同的字符串可以返回相同的哈希码,但我无法找到任何关于两个不同长度的字符串。这是可能的,如果是这样的话,将会受到赞赏。这是使用java哈希码函数,以防任何变化。
答案 0 :(得分:3)
Hashcodes分布在int
的空间内。 2^32 = ~4 billion
只有int
个可能的值。有很多可能的字符串,所以根据鸽子原则,必须存在多个具有相同哈希码的字符串。
但是,这并不能证明不同长度的字符串可能具有相同的哈希码,如下所述。 Java使用公式s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
进行散列字符串。知道了这一点,很容易构造具有相同哈希码的不同长度的字符串:
允许String s1 = "\001!";
和String s2 = "@";
。然后s1.length() != s2.length()
,但s1.hashCode() == '\001' * 31 + '!' == 1 * 31 + 33 == 64 == s2.hashCode() == '@' == 64
。
但是,让我再说一次int
的可能值超过4 亿,所以你的碰撞概率很低,虽然没有你想象的那么低,因为Birthday Paradox,它给你在大约77K哈希后有大约50%的碰撞几率(假设哈希是随机分布的,这实际上取决于你的数据 - 如果你主要处理非常小的长度字符串你会有更频繁的碰撞)。然而,使用散列处理的每个数据结构必须处理冲突(例如,常见的方式是在每个散列位置使用链表),或处理数据丢失(例如在布隆过滤器中)。
答案 1 :(得分:2)
是的,这可能发生。
一些相当简单的例子:
"foo"
,"\0foo"
,"\0\0foo"
等都具有相同的哈希码new String(new char[] { 12, 13 })
具有与单字符new String(new char[] { 12 * 31 + 13 })
相同的哈希码(我选择12
和13
的位置相同;相同适用于任何其他值,只要12 * 31 + 13
模拟值保持在两字节无符号整数范围内。)但这些只是一些易于构建的例子。尽管它们之间没有明显的关系,但也有很多字符串恰好碰巧具有相同的哈希码。