为什么java.util.HashMap中的备份表索引对于两个不同的提供键是相同的?

为什么java.util.HashMap中的备份表索引对于两个不同的提供键是相同的?,java,collections,hashmap,hashcode,Java,Collections,Hashmap,Hashcode,HashMap内部有方法hash(),该方法通过应用特殊函数来防止写得不好的哈希代码。 下一步是使用hash()方法返回的值来计算索引,新条目存储在名为table的后备数组中。 两个不同的键的索引可能是相同的。因为使用了链表,但我很清楚 为什么两个不同键的支持表索引可以相同? 我知道哈希代码可能被很差地重写,但方法hash()声明它可以防止哈希代码冲突。那个么为什么支持表的索引可以是相同的呢 编辑感谢所有回复@当您放入HashMap(大小)的元素数量大于或等于Threshold(根据构造函数中提

HashMap内部有方法hash(),该方法通过应用特殊函数来防止写得不好的哈希代码。 下一步是使用hash()方法返回的值来计算索引,新条目存储在名为table的后备数组中。 两个不同的键的索引可能是相同的。因为使用了链表,但我很清楚

为什么两个不同键的支持表索引可以相同?

我知道哈希代码可能被很差地重写,但方法hash()声明它可以防止哈希代码冲突。那个么为什么支持表的索引可以是相同的呢

编辑感谢所有回复@当您放入HashMap(大小)的元素数量大于或等于Threshold(根据构造函数中提供的initialCapacity和loadFactor计算)时,Dunkan-Jones resize会自动完成。查找方法createEntry-每当创建新条目时,大小都会增加。 我的问题是,为什么hash()方法+indexFor()方法为不同的对象返回相同的索引。由于索引相同,两个条目通过链表放在同一个存储桶中

是什么原因导致hash()+indexFor()方法返回相同的索引?

我想,也不知道那些棘手的>>>和&运算符会做什么

HashMap中的哈希是什么意思


再次感谢

您是对的,内部
hash()
方法用于提高
hashCode()
结果的质量。内部Javadocs描述了原因:

检索对象哈希代码并将补充哈希函数应用于 结果散列,用于防止质量差的散列函数。这是 关键是因为HashMap使用两个长度哈希表的幂,所以 否则,会遇到哈希代码的冲突,而哈希代码没有差异 在低位。注意:空键总是映射到散列0,因此索引为0

然而,您的潜在问题似乎是:为什么哈希映射允许多个值位于同一个“bucket”中,而不仅仅是扩展映射的大小?


答案将是性能。在调整大小操作期间,重新计算映射中的所有哈希值代价高昂。在某种程度上,将多个值塞进同一个bucket会更便宜。

如果我没记错的话,每个可以作为哈希映射键的对象都应该覆盖
hashCode()
方法,因此一般契约(来自Javadoc)是

如果根据
equals(Object)
方法,两个对象相等,那么对两个对象中的每一个调用
hashCode
方法必须产生相同的整数结果

换言之:

o1.equals(o2)
然后
o1.hashCode()==o2.hashCode()

哈希映射在内部使用另一个
Hash()
函数,该函数从
hashCode()
值创建另一个哈希代码。此函数在某些点使用模数(用于空间效率),因此不同的
hashCode()
值可以具有相等的
hash()
值(键映射为
hash()
值)

这不是问题,因为如果映射中的两个键具有equals
hash()
值,则在搜索时将与
equals()
方法进行比较,以确保它们具有相同的键,并且没有两个对象同时具有相同的hash代码

一些资源:

在OP编辑之后进行编辑 我认为
indexFor
计算模数。功能是

static int  indexFor(int h, int length) {
   return h & (length-1);
}
我们知道当b是2n时,
a%b==a&(b-1)
。长度字段(我们的“b”)是2n的倍数:

将补充哈希函数应用于给定的哈希代码,以防止出现低质量的哈希函数。这一点很关键,因为HashMap使用两个长度的幂次散列表,否则会遇到低位不不同的哈希代码冲突。注意:空键总是映射到散列0,因此索引为0


所以不同的散列值可以有相同的模数,所以不同的对象可以有相同的索引。

检查这个()因为这就是散列的意思。谢谢你的回复!不是,hash()方法用于防止编写糟糕的哈希代码,因为它接受哈希代码并应用特殊函数!接下来,使用hash()返回的值通过indexFor()方法确定支持表的索引。indexFor()使用按位&运算符应用支持表的长度,从而返回表边界内的索引。问题是为什么indexFor()返回的索引可以相同。谢谢,但为什么indexFor()可以为hash()的不同结果生成相同的索引。但是hash()可能会从不同的哈希代码生成相同的结果。我知道当没有足够的存储桶时,HashMap会自动增长,因此总是有足够的空间,并且HashMap会将两个条目放在同一个位置bucket@VolodymyrLevytskyi我编辑了我的答案,希望能解决你的实际问题。很酷的解释。谢谢