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

时间:2016-05-08 07:39:00

标签: java hashmap bucket

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

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

3 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:1)

取自How HashMap works in Java

  

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

然后当我们想要get列表中的equals()对象时,我们需要filebeat: prospectors: - paths: - /path/to/my/folder input_type: log # Optional additional fields. These field can be freely picked # to add additional information to the crawled log files fields: mycustomvar: production

  

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

答案 2 :(得分:0)

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 source