内部HashMap具有方法 hash(),它通过应用特殊函数来防止编写糟糕的哈希代码。 下一步是通过 hash()方法返回的值用于计算新条目存储在名为 table 的后备数组中的索引。 可能会发生 index 对于两个不同的键是相同的。因为使用了链接列表,但我很清楚。
为什么两个不同的密钥的支持表索引相同?
我知道哈希代码可能很难被覆盖,但方法 hash()表明它可以防止哈希代码冲突。那么为什么支持表的索引可以相同呢?
编辑感谢大家的回复。当您放入HashMap( size )的元素数量大于或等于阈值(根据构造函数中提供的initialCapacity和loadFactor计算)时,@ Dunkan Jones会自动调整大小。查看方法createEntry - 只要创建新Entry, size 就会递增。 我的问题是为什么hash()方法+ indexFor()方法为不同的对象返回相同的索引。由于这个相同的索引,两个条目通过链表放在同一个桶中。
什么原因导致hash()+ indexFor()方法返回相同的索引?
我认为并且无法通过那些棘手的>>>来实现hash()和indexFor()所做的事情。和&经营者?
HashMap中的哈希是什么意思?
再次感谢!
答案 0 :(得分:1)
您是对的,内部hash()
方法用于提高hashCode()
结果的质量。内部Javadocs描述了原因:
检索对象哈希码并将补充哈希函数应用于 结果哈希,防御质量差的哈希函数。这是 因为HashMap使用两个幂的长度哈希表,所以很关键 否则会遇到没有差异的hashCodes的冲突 低位。注意:空键始终映射到散列0,因此索引为0。
但是,您的基本问题似乎是:为什么哈希映射允许多个值位于同一个“存储桶”中,而不仅仅是扩展地图的大小?
答案将是表现。在调整大小操作期间重新计算地图中的所有哈希值很昂贵。在某一点上,将多个值填充到同一个桶中会更便宜。
答案 1 :(得分:1)
如果我没记错的话,每个可以作为哈希映射键的对象都应该覆盖hashCode()
方法,所以一般契约(来自Javadoc)是
如果两个对象根据
equals(Object)
方法相等,则在两个对象中的每一个上调用hashCode
方法必须产生相同的整数结果。
换句话说:
o1.equals(o2)
然后o1.hashCode() == o2.hashCode()
哈希映射在内部使用另一个hash()
函数,该函数从hashCode()
值创建另一个哈希码。此函数在某些时候使用模数(对于空间效率),因此不同的hashCode()
值可以等于hash()
值(键与hash()
值映射)。
这不是问题,因为如果地图中的两个键具有等于hash()
值,则在搜索时将与equals()
方法进行比较,以确保它们具有相同的键,并且没有两个对象巧合的是,它具有相同的哈希码。
一些资源:
我认为indexFor
计算模数。功能是
static int indexFor(int h, int length) {
return h & (length-1);
}
我们知道(来自theory)a % b == a & (b - 1)
iff b 是2 n 。长度字段(我们的“ b ”)是2 n 的倍数:
将补充哈希函数应用于给定的hashCode,以防御质量差的哈希函数。这很关键,因为HashMap使用两个幂的长度哈希表,否则会遇到低位不同的hashCodes的冲突。注意:空键始终映射到散列0,因此索引为0。
因此不同的哈希值可以具有相同的模数,因此不同的对象可以具有相同的索引。