[英]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的内部数组是固定大小的,并且如果你继续存储对象,在某些时候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。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.