当前位置: 首页 > 面试题库 >

HashMap调整大小方法的实现细节

狄珂
2023-03-14
问题内容

如标题所示,这是一个有关实现细节的问题HashMap#resize-那是内部数组的大小加倍时。有点罗word,但我确实试图证明我已尽力了解这一点…

这是在此特定存储桶/存储箱中的条目以某种方式存储的时候发生的Linked-因此具有确切的顺序,在问题的上下文中, 这一点很重要

通常,resize也可以从其他地方调用,但是让我们只看这种情况。

假设您将这些字符串作为键放入HashMap(在右侧,hashcode 后面是 HashMap#hash-内部重新哈希。)是的,它们是精心生成的,而不是随机生成的。

 DFHXR - 11111
 YSXFJ - 01111 
 TUDDY - 11111 
 AXVUH - 01111 
 RUTWZ - 11111
 DEDUC - 01111
 WFCVW - 11111
 ZETCU - 01111
 GCVUR - 11111

这里有一个简单的模式-所有的后4位都是相同的-
这意味着当我们插入8个键(总共9个)时,它们将最终出现在同一存储桶中;并在9个HashMap#put时,resize将被调用。

因此,如果当前-中有8个条目(具有上面的键之一),HashMap则表示此映射中有16个存储桶,它们的后4位键决定了这些条目的结尾位置。

我们输入了第九把钥匙。这时TREEIFY_THRESHOLD被点击并被resize调用。垃圾箱被加倍,32并且按键的另外一位决定该条目的去向(因此,现在为5位)。

最终,到达了这段代码(resize发生时):

 Node<K,V> loHead = null, loTail = null;
 Node<K,V> hiHead = null, hiTail = null;
 Node<K,V> next;
 do {
     next = e.next;
     if ((e.hash & oldCap) == 0) {
          if (loTail == null)
               loHead = e;
          else
               loTail.next = e;
          loTail = e;
     }
     else {
        if (hiTail == null)
            hiHead = e;
        else
            hiTail.next = e;
        hiTail = e;
     }
 } while ((e = next) != null);



 if (loTail != null) {
     loTail.next = null;
     newTab[j] = loHead;
 }
 if (hiTail != null) {
     hiTail.next = null;
     newTab[j + oldCap] = hiHead;
 }

实际上,它并不那么复杂…它将当前的bin分为 将移至 其他bin的条目和 不会移至 其他bin的条目-但可以肯定地保留在该条目中。

实际上,如何做到这一点非常聪明-通过以下代码:

 if ((e.hash & oldCap) == 0)

这是检查下一个位(在我们的例子中为第五位)是否实际上为零-如果为零,则意味着该条目将保持在原位置;如果不是,它将在新料箱中以两个偏移量移动。

现在最后是一个问题:调整大小的那段代码是精心制作的,以便 保留该 bin中 条目的顺序

因此,在将这9个键放入HashMap顺序后,顺序将是:

DFHXR -> TUDDY -> RUTWZ -> WFCVW -> GCVUR (one bin)

YSXFJ -> AXVUH -> DEDUC -> ZETCU (another bin)

为什么要保留。中某些条目的顺序HashMap?在订单Map是 _真的_详见坏在这里。


问题答案:

设计注意事项已记录在同一源文件中的第211行的代码注释中

* When bin lists are treeified, split, or untreeified, we keep
* them in the same relative access/traversal order (i.e., field
* Node.next) to better preserve locality, and to slightly
* simplify handling of splits and traversals that invoke
* iterator.remove. When using comparators on insertion, to keep a
* total ordering (or as close as is required here) across
* rebalancings, we compare classes and identityHashCodes as
* tie-breakers.

由于通过迭代器删除映射无法触发调整大小,因此专门保留顺序的原因resize是“更好地保留局部性,并稍微简化拆分的处理”,以及在策略上保持一致。



 类似资料:
  • 本文向大家介绍Pycharm 字体大小调整设置的方法实现,包括了Pycharm 字体大小调整设置的方法实现的使用技巧和注意事项,需要的朋友参考一下 一、pycharm字体放大的设置 File —>setting —> Keymap —>在搜寻框中输入increase —>Increase Font Size(双击) —> 在弹出的对话框中选择Add Mouse Shortcut 在弹出的对话框中同

  • 本文向大家介绍php实现在服务器端调整图片大小的方法,包括了php实现在服务器端调整图片大小的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了php实现在服务器端调整图片大小的方法。分享给大家供大家参考。具体分析如下: 在服务器端完成图片大小的调整,会比在浏览器的处理有很多的好处。 本文介绍了PHP如何在服务器端调整图片大小。 代码包括两部分: ① imageResizer() is

  • 本文向大家介绍jquery实现拖拽调整Div大小,包括了jquery实现拖拽调整Div大小的使用技巧和注意事项,需要的朋友参考一下 今天写了一天这个jquery插件: 可以实现对div进行拖拽来调整大小的功能。  记录一下今天的劳动成果,可能会有很多不成熟的地方,欢迎大家来指正,谢谢! 以上就是本文的全部内容了,希望大家能够喜欢。

  • 问题内容: A 在其文档中有这样的短语: 如果初始容量大于最大条目数除以负载因子,则将 不会 发生任何哈希操作。 请注意文档中说的是 rehash ,而不是 resize- 即使仅在调整大小时才会发生rehash;也就是说,当存储桶的内部尺寸变大两倍时。 当然提供了这样的构造函数,我们可以在其中定义此 初始容量 。 构造一个具有指定初始容量和默认负载因子(0.75)的空HashMap。 OK,看起

  • 我正在学习一个教程,它基本上解释了在多线程环境中调整Hashmap大小时出现争用条件的原因: 在Java中,如果两个线程同时发现现在HashMap需要调整大小,那么它们都尝试调整大小。Java HashMap在调整HashMap大小的过程中,链表中存储的bucket中的元素在迁移到新bucket时被颠倒,因为Java HashMap不在尾部追加新元素,而是在头部追加新元素,以避免尾部遍历。如果竞争

  • 问题内容: 在放入HashMap期间发生冲突时,是否会调整地图大小或将条目添加到该特定存储桶中的列表中? 问题答案: 当您说“冲突”时,您是指相同的哈希码吗?哈希码用于确定要使用HashMap中的哪个存储桶,并且该存储桶由具有相同哈希码的所有条目的链表组成。然后在返回或引导(获取/放入)之前比较条目的相等性(使用.equals())。 请注意,这是专门用于HashMap的(因为这是您所要求的),而