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



我理解当我们声明如下地图时:

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

默认荷载系数为 0.75,大小为 16,当地图的桶数超过 12 个元素时,大小变为 32。

但是,在使用 put 函数时,地图选择将放置对象的存储桶索引的方式由hascode % n但是当映射大小超过负载系数时会发生什么? n 不再具有相同的值,因此,如果, 应用hascode % n时,得到的索引会不会和以前不一样?

我的最后一个问题是:

我们增加大小后,存储桶的索引如何相同?

简单的答案是存储桶的索引不一定相同。HashMap必须在展开时对所有元素执行重新散列。

请参阅以下方法:

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

resize.JavaDoc说

将此映射的内容重新散列到具有更大 能力。 当键数增加时自动调用此方法 在此地图中达到其阈值。

强调我的

另请参阅:

哈希
  • 图或哈希表中的重新哈希过程
  • 如何在哈希图中以及何时完成重新哈希
  • 在 Java 中的 HashMap 中重新散列

HashMap的默认初始容量为 16,负载系数为 0.75f(即当前地图大小的 75%(。 负载系数表示HashMap容量应加倍的水平。

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

为了进一步暴露

进一步的流程说明

当 映射达到最大阈值。

通常负载系数值为 0.75,默认初始容量 值为 16。一旦元素数达到或交叉0.75次 容量,然后进行地图的重新散列。在这种情况下,当 元素数为 12,然后进行重新哈希。(0.75 * 16 = 12(

当重新哈希发生新的哈希函数甚至相同的哈希时 可以使用函数,但存在值的存储桶 可以改变。基本上,当重新散列发生时,存储桶的数量 大约翻倍,因此新索引的值 必须做出改变。

在重新散列时,每个存储桶的链表都会在 次序。发生这种情况是因为 HashMap 不会在 尾巴 相反,它会在头部附加新元素。所以当 发生重新散列,它读取每个元素并将其插入新的 桶在头部,然后继续添加旧元素的下一个元素 地图位于新地图的头部,导致链表反转。

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

详细说明了上述无限循环是如何发生的 案例可以在这里找到:

阅读本文以加深理解

如果插入到映射中的元素必须对键进行排序,则 可以使用树状图。但是,如果顺序为 钥匙无关紧要。

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

当哈希表中的

条目数超过负载因子与当前容量的乘积时,将重新哈希哈希表(即重建内部数据结构(,以便哈希表中的存储桶数大约是其两倍。

哈希图不保留排序。看看使用LinkedHashMaps。

最新更新