HashMap put(),resize()解析

HashMap put(),resize()解析

查看的源码是jdk1.8版本,这里对jdk1.7的HashMap不详细讨论

map常量讲解:

首先,先看看HashMap定义的常量
在这里插入图片描述在这里插入图片描述

前三个分别是默认容量=16,最大容量=2^30,默认的负载因子=0.75。当map里的节点大小大于总容量*负载因子时,会进行扩容。
后三个分别是树化长度=8,退化长度=6,以及最小的树化容量=64。jdk1.8中,HashMap的实现是数组加链表加红黑树,当链表长度大于等于8,进行树化,但是首先还要Map的容量大于最小树化容量64,才可以进行树化。

put函数解析

在这里插入图片描述调用put函数,会先通过hash(key)计算key的hash值,onlyIfAbsent的值是指是否允许修改已经存在的key的value值。默认是同意的。代码逻辑如下,传过来的值是false,所以默认就是会替换值。
在这里插入图片描述之后进入putVal函数里面了
在这里插入图片描述如果我们调用newHashMap<>()函数创建Map,一开始的时候,表是没有创建的,所以会先扩容,容量为16。
之后,计算下标(n-1)& hash,计算完了就插入到table表中,如果对应的下标一个节点没有,就直接创建。如果有节点,就遍历判断是不是已经存在key值,如果存在要进行值的替换。如果发现已经是树节点了,就进入树的添加环节。如果遍历到尾部发现还是没有相同的key值,就在尾部添加节点。

当执行完插入过程后,就到了判断是否需要扩容的环节了。先插入,后判断是否需要扩容。

在这里插入图片描述threshold属性的计算是容量*负载因子。可以将threshold理解为扩容的阈值

resize函数解析

resize函数做了两件事情,一是计算新的容量,和新的阈值大小。二是将旧的节点移到新的表。

计算新容量,新阈值,分为三种情况,一是空参创建,二是指定了容量创建,三是已经有表,正常的扩容。
在这里插入图片描述在指定容量创建的时候,也是不创建表的,把容量的数值存放在了threshold属性里。
如果已经存在表了,那就进行正常的扩容过程,容量2,阈值2。如果长度已经大于等于最大容量,就不扩容。
最后就是将旧表中的节点放到新表(table是Node节点类型的数组)中,在这里其实1.8有了一个巧妙的计算下标的方式,如下图
在这里插入图片描述

因为length,其实就是容量是保证了其值是2^n的,所以length-1&hash计算下标不会导致下标越界。同时,新的length(新容量)其实就是旧容量左移一位。所以可以巧妙的计算新下标的值要么是原来的,要么是原来的加上旧容量长度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值