如标题所示,这是一个有关实现细节的问题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的(因为这是您所要求的),而