繁体   English   中英

具有不同hashCode的两个密钥可以在Java中的HashMap中成为同一个存储桶的一部分吗?

[英]Can two keys having different hashCode be a part of same bucket in HashMap in Java?

我有一个HashMap。 它有16个桶(默认情况下)。 现在有两个具有不同hashCodes的密钥可能是同一个桶的一部分吗? 或者它总是为不同的hashCode创建一个新的桶,这样HashMap扩展了桶的大小?

阅读很多帖子,但只是困惑自己。

对的,这是可能的。 由于桶的数量远小于可能的hashCodes的数量(桶的数量与HashMap的条目数成比例,而可能的hashCodes的数量是可能的int值的数量,这是更大的), hashCode到存储桶的最终映射是由某个模数运算符完成的,因此可以将多个hashCodes映射到同一个存储桶(例如,如果您有16个存储桶,则hashCodes 1和17都将映射到同一个存储桶(请注意,通过hashCode我并不是指hashCode方法返回的值,因为HashMap在该hashCode上应用了一个额外的函数,以便改善哈希码的分布))。

这就是为什么单独的hashCode不足以确定我们正在寻找的密钥是否存在于地图中 - 我们也必须使用equals

摘自HashMap如何在Java中工作

由于HashMap的内部数组是固定大小的,并且如果你继续存储对象,在某些时候hash函数将为两个不同的键返回相同的bucket位置,这在HashMap中称为碰撞。 在这种情况下,在该桶位置处形成链表,并且将新条目存储为下一节点。

然后当我们想要从列表中get该对象时,我们需要equals()

如果我们尝试从此链表中检索对象,我们需要额外检查以搜索正确的值,这是通过equals()方法完成的。 由于每个节点都包含一个条目,HashMap使用equals()保持比较条目的密钥对象和传递的密钥,当它返回true时,Map返回相应的值。

hashcode()在java中返回interger,因此您必须将整数范围映射到bucket大小。 如果要从较大的集映射到较小的集,则始终存在冲突。 如果查看HashMap源代码,您将找到以下方法将int映射到存储区长度。

 static int indexFor(int h, int length) {
             return h & (length-1);
 } 

使用以下方法预处理哈希码以产生均匀分布:

static int hash(int h) {
         // This function ensures that hashCodes that differ only by
         // constant multiples at each bit position have a bounded
         // number of collisions (approximately 8 at default load factor).
         h ^= (h >>> 20) ^ (h >>> 12);
         return h ^ (h >>> 7) ^ (h >>> 4);
     }

将补充哈希函数应用于给定的hashCode,以防御质量差的哈希函数。 这很关键,因为HashMap使用两个幂的长度哈希表,否则会遇到低位不同的hashCodes的冲突。 注意:空键始终映射到散列0,因此索引为0。

HashMap源码

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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