阅读JDK的源代码后,我仍然对字符串感到惊讶
"AaAa", "AaBB" and "BBBB"
具有相同的哈希码。
JDK的来源如下,
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
任何人都可以澄清吗?
答案 0 :(得分:5)
因为the hash code is defined to be calculated for a String
就是这样:
字符串对象的哈希码计算为
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
所以:
AaAa
:65*31^3 + 97*31^2 + 65*31 + 97 = 2031744
AaBB
:65*31^3 + 97*31^2 + 66*31 + 66 = 2031744
BBBB
:66*31^3 + 66*31^2 + 66*31 + 66 = 2031744
答案 1 :(得分:5)
因为probability。
大约有40亿个哈希码(Integer.MIN_VALUE -> Integer.MAX_VALUE
)和基本上无限的字符串。必然会有collisions。实际上,the birthday problem向我们展示了that only ~77,000 strings是发生任意冲突的高概率所必需的-这就是说,如果散列函数具有极高的熵(不是)。
也许您在想一个cryptographic hash function,其中
对消息进行少量更改应更改哈希值,因此 新哈希值似乎与旧哈希值不相关 哈希值
在这种情况下,Object.hashCode
并非用于加密目的。
答案 2 :(得分:3)
他们的哈希码是
AaAa: ((65 * 31 + 97) * 31 + 65) * 31 + 97 = 2.031.744
AaBB: ((65 * 31 + 97) * 31 + 66) * 31 + 66 = 2.031.744
BBBB: ((66 * 31 + 66) * 31 + 66) * 31 + 66 = 2.031.744
这就是数学原理,没什么可混淆的。
请注意,97和66之间恰好是31的区别,这就是使这些哈希码排列得如此好的原因。
答案 3 :(得分:1)
这是Java文档中Dict {
key_equivalent =
enabled_context_menu = false
enabled_services_menu = false
}
方法的说明:
只要在执行Java应用程序期间在同一个对象上多次调用它,
Object#hashCode
方法就必须一致地返回相同的整数,前提是没有hashCode
比较中使用的信息修改。从一个应用程序的一个执行到同一应用程序的另一个执行,此整数不必保持一致。如果根据
equals
方法两个对象相等,则在两个对象中的每个对象上调用equals(Object)
方法必须产生相同的整数结果。根据
hashCode
方法,如果两个对象不相等,则不需要在两个对象中的每一个上调用java.lang.Object#equals(java.lang.Object)
方法必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。
因此,hashCode
类的实现也保持了上述特征。这是正常现象。
答案 4 :(得分:0)
有几种类型的哈希函数具有不同的设计和性能标准。
用于索引的哈希函数(例如关联数组和类似用法)可能会发生频繁冲突而不会出现问题,因为哈希表代码随后将在某些命名器中处理该问题,例如将它们放入列表或重新哈希。这就是时间的性能。 Java hash()
似乎是这种类型
另一种类型的函数,例如SHA *等加密哈希,以哈希性能为代价,努力避免冲突。
第三种哈希函数是密码验证器哈希,它设计得非常慢(通常为100毫秒左右),可能需要大量内存,因此不常发生冲突不是问题。这里的目的是要使蛮力攻击花费尽可能长的时间。
一次根据使用情况选择哈希的类型和特征。