[英]Why the following three strings's hashcode are same?
在阅读了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;
任何人都可以澄清吗?
因为这就是定义要为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
他们的哈希码是
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的区别,这就是使这些哈希码排列得如此好的原因。
这是来自Java文档中的Object#hashCode
方法的描述:
在Java应用程序执行期间,只要在同一对象上多次调用它,
hashCode
方法就必须一致地返回相同的整数,前提是不修改该对象的equals
比较中使用的信息。此整数不必与一个整数保持一致一个应用程序的执行到同一应用程序的另一个执行。如果根据
equals(Object)
方法,两个对象相等,则在两个对象中的每个对象上调用hashCode
方法必须产生相同的整数结果。根据
java.lang.Object#equals(java.lang.Object)
方法,如果两个对象不相等,则不需要在两个对象中的每个对象上调用hashCode
方法必须产生不同的整数结果。 但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。
因此, String
类的实现也保持了上述特征。这是正常现象。
有几种类型的哈希函数具有不同的设计和性能标准。
用于索引的哈希函数(例如关联数组和类似用法)可能会发生频繁冲突而不会出现问题,因为哈希表代码将随后以某种名称处理该代码,例如将其放入列表或重新哈希。 这就是时间的性能。 Java hash()
似乎是这种类型的
另一类函数,例如SHA *等加密哈希,以哈希性能为代价,努力避免冲突。
第三种散列函数是密码验证器散列,密码散列被设计为非常慢(通常为100毫秒左右),并且可能需要大量内存,因此不会出现频繁冲突。 这里的目的是要使蛮力攻击花费尽可能长的时间以至于不可行。
根据用途选择哈希的类型和特征。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.