【问题标题】:Can two strings of different length have the same hashcode?两个不同长度的字符串可以具有相同的哈希码吗?
【发布时间】:2017-02-14 17:07:05
【问题描述】:

虽然我知道两个不同的字符串可以返回相同的哈希码,但我一直无法找到关于两个不同长度的任何信息。这是否可能,如果可以,将不胜感激。这是使用 java hashcode 函数,以防万一发生任何变化。

【问题讨论】:

标签: java string hashcode


【解决方案1】:

哈希码分布在int 的空间中。对于int,只有2^32 = ~4 billion 可能的值。可能的字符串远不止这个数量,因此根据鸽巢原理,必须存在多个具有相同哈希码的字符串。

但是,这并不能证明不同长度的字符串可能具有相同的哈希码,如下所述。 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 有超过 40 亿 个可能的值,所以你的碰撞概率很低,虽然没有你想象的那么低,因为Birthday Paradox,这使您在大约 77K 散列后有大约 50% 的机会发生冲突(假设散列是随机分布的,这实际上取决于您的数据 - 如果您主要处理长度非常小的字符串,您将遇到更频繁的冲突)。但是,每个使用散列处理的数据结构都必须处理冲突(例如,一种常见的方法是在每个散列位置使用链表),或者处理数据丢失(例如在布隆过滤器中)。

【讨论】:

  • 这并不能回答长度是否重要。例如,如果哈希码类似于 someFunction(theString)
【解决方案2】:

是的,这可能发生。

一些相当琐碎的例子:

  • 初始零值字符不会影响哈希码,因此(例如)"foo""\0foo""\0\0foo" 等都具有相同的哈希码。
  • 每个字符在添加下一个字符之前只需乘以 31;所以(例如)两个字符的字符串new String(new char[] { 12, 13 }) 与单字符new String(new char[] { 12 * 31 + 13 }) 具有相同的哈希码(我任意选择了1213;对于任何其他值,只要因为12 * 31 + 13 模拟保持在两字节无符号整数范围内)。

但这些只是一些易于构建的示例。还有很多字符串对恰好具有相同的哈希码,尽管它们之间没有明显的关系。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 2020-12-29
    • 2012-07-19
    • 2013-04-30
    • 1970-01-01
    • 2011-07-23
    相关资源
    最近更新 更多