美文网首页
记录读源码-HashMap(2)

记录读源码-HashMap(2)

作者: 浅笑丨无痕 | 来源:发表于2018-04-17 01:19 被阅读0次

1.HashMap的扩容机制

  HashMap内部提供了resize()方法,该方法主要用于初始化生成table数组以及将原来的table数组(下面称为桶)进行扩容,HashMap按当前桶数组长度的2倍进行扩容。在扩容两倍之后, 原来数组中存放的Node要存放到新的数组中,重新计算键值对的位置,并把它们移动到合适的位置上去.  接下来我们来看看具体的实现:

  源码比较长,提取出来大概做了这几件事:

  1.重新计算数组大小newCap,以及新的临界值newThr;

  2.初始化新的数组,并将旧的数组中键值对节点重新映射到新的桶数组里

  对步骤1进行分解:

对步骤2中重新映射节点进行分解:

重新映射节点需要考虑节点类型。对于树形节点,需先拆分红黑树再映射。对于链表类型节点,则需先对链表进行分组,然后再映射。关于红黑树拆分的逻辑后面再说,先来看看链表是怎样进行分组映射的。

从源码中可以看出:元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置,也就是说原索引的位置和在原索引+oldCap的位置。看下图可以明白这句话的意思,n为table的长度,图(a)表示扩容前的key1和key2两种key确定索引位置的示例,图(b)表示扩容后key1和key2两种key确定索引位置的示例,其中hash1是key1对应的哈希与高位运算结果。

  元素在重新计算hash之后,因为n变为2倍,那么n-1的mask范围在高位多1bit(红色),因此新的index就会发生这样的变化

2.树化

  链表树化是jdk1.8中HashMap新增加的一个优化,虽然降低了处理频繁的碰撞,代码复杂度也随之上升。笔者对红黑树不是很熟悉,只知道红黑树是一种自平衡的二叉查找树,本身就比较复杂。所以笔记不对红黑树展开描述,有需要了解请自行搜索学习。

  先来看一下链表转树的源码:

  从源码可以看到,当桶数组的长度较小时,如果节点超过阈值时,优先是扩容,优先扩容可以避免一些列的不必要的树化过程。同时,桶容量较小时,扩容会比较频繁,扩容时需要拆分红黑树并重新映射。所以在桶容量比较小的情况下,树化反而变成吃力不讨好,增加复杂度。HashMap具体怎么树化就不继续深入探究了。

相关文章

  • 记录读源码-HashMap(2)

    1.HashMap的扩容机制 HashMap内部提供了resize()方法,该方法主要用于初始化生成table数...

  • 记录读源码-HashMap(1)

    HashMa源码很久没看了,有点忘记,还是得做点笔记 1.HashMap中定义的常量 1.默认容量 static ...

  • LinkedHashMap源码简读

    LinkedHashMap源码简读 1、LinkedHashMap继承自HashMap,HashMap具有的特性它...

  • HashMap 源码阅读

    HashMap 源码阅读 之前读过一些类的源码,近来发现都忘了,再读一遍整理记录一下。这次读的是 JDK 11 的...

  • HashMap源码分析——put和get(二)

    HashMap源码分析——put和get(二) 链接 上一节 :HashMap源码分析——put和get(一) 2...

  • HashMap解读

    相信大家对HashMap都非常熟悉, 网上也有很多关于hashmap的源码解析, 此文仅记录本人对HashMap的...

  • HashMap剖析

    Java集合:HashMap源码剖析 一、HashMap概述 二、HashMap的数据结构 三、HashMap源码...

  • JDK1.8中HashMap底层实现原理

    接下来会从以下几个方面介绍 HashMap 源码相关知识: 1、HashMap 存储结构 2、HashMap 各常...

  • HashMap源码

    HashMap的源码,基于jdk1.7Map的源码 AbstractMap的源码 HashMap的源码

  • 读源码-HashMap

    致第的第一次(读源码):突然发现,我不再年轻了,已经到了不得不改变了年纪,自己生命的宽度不够,深度也不够,再不非凡...

网友评论

      本文标题:记录读源码-HashMap(2)

      本文链接:https://www.haomeiwen.com/subject/uvgykftx.html