Java 为什么要使用以下三个字符串';hashcode是相同的吗?
在阅读了JDK的源代码之后,我仍然对字符串Java 为什么要使用以下三个字符串';hashcode是相同的吗?,java,string,hashcode,Java,String,Hashcode,在阅读了JDK的源代码之后,我仍然对字符串 “AaAa”、“AaBB”和“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; } retur
“AaAa”、“AaBB”和“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;
inth=hash;
如果(h==0&&value.length>0){
char val[]=值;
for(int i=0;i
任何人都可以澄清这一点?因为这就是为什么:
字符串对象的哈希代码计算为
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的差异,这就是为什么这些哈希代码排列得如此整齐。因为
大约有40亿个可能的哈希代码(Integer.MIN\u VALUE->Integer.MAX\u VALUE
)和基本上无限的可能字符串。肯定会有。事实上,如果哈希函数具有极高的熵,那么任意冲突的可能性就很高,而事实并非如此
也许你在想一个,在哪里
对消息的一个小更改应该会更改哈希值,以便
新的散列值似乎与旧的散列值不相关
散列值
在这种情况下,Object.hashCode
不是为加密目的而设计的
另请参见以下是Java文档中对对象#hashCode
方法的描述:
在Java应用程序执行期间,每当在同一对象上多次调用它时,hashCode
方法必须始终返回相同的整数,如果对象上的equals
比较中使用的信息未被修改,则该整数不必在应用程序的一次执行与同一应用程序的另一次执行之间保持一致
如果根据equals(Object)
方法,两个对象相等,那么对两个对象中的每一个调用hashCode
方法必须产生相同的整数结果
根据java.lang.Object#equals(java.lang.Object)
方法,如果两个对象不相等,则对这两个对象中的每一个调用hashCode
方法都必须产生不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同的整数结果可能会提高哈希表的性能
因此,String
类的实现也保持了上述特征。因此这是一种正常现象。有几种不同设计和性能标准的哈希函数
用于索引的散列函数(如关联数组和类似用法)可能会经常发生冲突,这是没有问题的,因为散列表代码随后将以某种名称处理这些函数,例如将它们放入列表或重新散列。这里的一切都是关于时间的表现。Javahash()
似乎属于这种类型
另一种类型的函数是加密散列,如SHA*,它以牺牲散列性能为代价,努力避免冲突
然而,第三种类型的散列函数是密码验证器散列,其设计速度非常慢(通常约100ms),可能需要大量内存,并且不需要担心频繁的冲突。这里的要点是让暴力攻击尽可能长时间不可行
Once根据使用情况选择哈希的类型和特征。这到底是为什么让您感到惊讶?散列码不是唯一的,将有不同的字符串具有相同的散列码,并且您碰巧发现了三个。“Aa”
和“BB”
具有相同的散列码。因此,相同长度的“Aa”
或“BB”
序列将具有相同的哈希代码。@Jesper有些人可能会感到惊讶,为什么他们有过努力避免冲突的加密哈希函数的经验。看起来很容易发生冲突?为什么选择这个散列函数?@AdamLee因为它计算简单,平均来说效果很好。并且它是公共API的一部分,因此不可能对其进行更改。@AdamLee,因为使哈希冲突的查找变得困难过去是,现在也不是此哈希函数的目标之一。@AdamLee冲突是预期的,不应避免或避免。Equal哈希代码并不表示对象是相等的,但只有它们可以是相等的。请参阅Java以更好地了解其用途。也许值得指出的是,由于,仅77400个实例更可能发生哈希冲突。@Andy Turner您是如何计算77k的?它位于链接表的p=0.50
列的第一行。我怎么知道是77.4k?不确定-这是我刚才。。。“知道”。我可能记错了:)@AndyTurner记得很清楚。差不多就在。。。(如果你想拍自己的背,可以添加一个链接)