![](/img/trans.png)
[英]Why member field 'table' in 'java.util.HashMap' is transient?
[英]Why can index of backing table in java.util.HashMap be the same for two different provided keys?
内部HashMap有方法hash() ,它通过应用特殊函数来防止写得不好的哈希代码。 下一步是使用hash()方法返回的值来计算新条目存储在名为table的后备数组中的索引。 可能会发生两个不同键的索引相同。 因为使用了链表但我很清楚。
为什么两个不同键的支持表索引相同?
我知道哈希代码可能很难被覆盖,但方法hash()声明它可以防止哈希代码冲突。 那么为什么支持表的索引是一样的呢?
编辑感谢大家的回复。 当您放入HashMap( 大小 )的元素数量大于或等于阈值(根据构造函数中提供的initialCapacity和loadFactor计算)时,@ Dunkan Jones会自动调整大小。 查看方法createEntry - 每当创建新Entry时, size都会递增。 我的问题是为什么hash()方法+ indexFor()方法为不同的对象返回相同的索引。 由于这个相同的索引,两个条目通过链表放在同一个桶中。
是什么导致hash()+ indexFor()方法返回相同的索引?
我认为并且无法通过那些棘手的>>>和&运算符来实现hash()和indexFor()所做的事情?
HashMap中的哈希意味着什么?
再次感谢!
你是对的,内部的hash()
方法用于提高hashCode()
结果的质量。 内部Javadocs描述了原因:
检索对象哈希码并将补充哈希函数应用于结果哈希,以防止质量差的哈希函数。 这很关键,因为HashMap使用两个幂的长度哈希表,否则会遇到低位不同的hashCodes的冲突。 注意:空键始终映射到散列0,因此索引为0。
但是,您的基本问题似乎是: 为什么哈希映射允许多个值位于相同的“存储桶”中而不是仅仅扩展地图的大小?
答案将是表现。 在调整大小操作期间重新计算地图中的所有哈希值很昂贵。 在某一点上,将多个值填充到同一个桶中会更便宜。
如果我没记错的话,每个可以作为哈希映射关键字的对象都应该覆盖hashCode()
方法,所以一般契约(来自Javadoc)是
如果两个对象根据
equals(Object)
方法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);
}
我们知道(从理论上 ) a % b == a & (b - 1)
iff b是2 n 。 长度字段(我们的“ b ”)是2 n的倍数:
将补充哈希函数应用于给定的hashCode,以防御质量差的哈希函数。 这很关键,因为HashMap使用两个幂的长度哈希表,否则会遇到低位不同的hashCodes的冲突。 注意:空键始终映射到散列0,因此索引为0。
因此不同的哈希值可以具有相同的模数,因此不同的对象可以具有相同的索引
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.