繁体   English   中英

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

[英]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()方法进行比较,以确保它们具有相同的键,并且没有两个对象巧合地具有相同的哈希码。

一些资源:

OP编辑后编辑

我认为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM