提问者:小点点

当HashMap增加其大小时,HashMap中值的索引会发生什么?


我明白,当我们声明如下地图时:

Map <String, Integer> map = new HashMap ();

默认加载因子为0.75,其大小为16,当地图的桶超过12个元素的数量时,大小将变为32。

然而,当使用put函数时,map选择将放置对象的桶的索引的方式是由hascode%n定义的,但是当map大小超过加载因子时会发生什么?n不再具有相同的值,因此,如果在应用hascode%n时,结果索引将与以前不同,您如何找到先前设置的条目?

我的最后一个问题是:

我们增加大小后,桶的索引怎么会一样?


共3个答案

匿名用户

简单的答案是它不能。HashMap必须在扩展时对所有元素执行重新散列。

请参阅以下方法:

/**
 * Transfers all entries from current table to newTable.
 */
void transfer(Entry[] newTable, boolean rehash) {

resize调用。其中的JavaDoc说

将此映射的内容重新散列为具有更大容量的新数组。当此映射中的键数达到其阈值时,会自动调用此方法。

强调我的

另见:

  • hashmap或hashtable中的重新散列过程
  • 如何以及何时在HashMap中完成重新散列
  • 在Java的HashMap中重新散列

匿名用户

HashMap的默认初始容量为16,负载因子为0.75f(即当前地图大小的75%)。负载因子表示HashMap容量应该翻倍的级别。

例如容量和负载因子的乘积为16*0.75=12。这表示将第12个键值对存储到HashMap后,其容量变为32。

供进一步曝光

进一步的过程解释

哈希映射的重新散列是在映射中的元素数量达到最大阈值时完成的。

通常负载因子值为0.75,默认初始容量值为16。一旦元素数量达到或超过容量的0.75倍,就会发生map的rehash。在这种情况下,当元素数量为12时,就会发生rehash。(0.75*16=12)

当重新散列发生时,可以使用新的散列函数,甚至可以使用相同的散列函数,但是值所在的桶可能会发生变化。基本上,当重新散列发生时,桶的数量大约增加了一倍,因此必须放置值的新索引会发生变化。

重新散列时,每个桶的链表顺序颠倒。发生这种情况是因为HashMap不会在尾部附加新元素,而是在头部附加新元素。因此,当重新散列发生时,它会读取每个元素并将其插入头部的新桶中,然后继续从新地图头部的旧地图中添加下一个元素,从而导致链表颠倒。

如果有多个线程处理相同的哈希映射,则可能导致无限循环。

说明无限循环如何在上述情况下发生的详细解释可以在这里找到:

阅读本文以获得更多理解

如果映射中插入的元素必须根据键进行排序,那么可以使用TreeMap。但是如果键的顺序无关紧要,HashMap会更有效。

匿名用户

内部数据结构重建。来自文档:https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html:

当哈希表中的条目数量超过负载因子和当前容量的乘积时,哈希表被重新散列(即重建内部数据结构),以便哈希表具有大约两倍的存储桶数量。