带你走进Java集合-HashMap源码-put方法的源码解析

本文详细剖析了HashMap的put方法,从put方法到putVal方法,再到红黑树的插入逻辑,揭示了HashMap在存储键值对时的内部运作。首先,put方法将任务委托给putVal,接着检查底层数组是否初始化,如果未初始化则进行resize。然后通过hash计算键值对在数组中的位置,如果该位置为空,则直接插入;如果已有节点,判断是否为红黑树,如果是则按照红黑树规则插入;否则,遍历链表进行插入。在链表达到一定长度时,HashMap会将其转换为红黑树,提高查找效率。最后,根据onlyIfAbsent参数决定是否覆盖旧值,并在必要时进行扩容。
摘要由CSDN通过智能技术生成

本篇文章内容较长,请耐心观看,相信对您理解HashMap的put方法会有所帮助。

在HashMap中put方法的源码如下:

public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
这个put方法并没有做任何的操作,直接把任务交给了putVal方法。我们接下来去看putVal方法。首先贴出putVal的声明:

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict)
hash:就是举例中的"a"的hash值
key:就是举例中的"a"
value:就是举例中的5
onlyIfAbsent:官方给的解释:@param onlyIfAbsent if true, don’t change existing value
,如果为true,将不能改变已经存在的值,举个例子:集合map中已经存在key=“a”,value=3,
如果onlyIfAbsent=true,在添加key=“a”,value=5,那么key="a"对应的值不会被改变,还是3。我们经常使用的put方法,此参数的值是false,说明put方法可以覆盖已经存在的值。
evict:参数用于LinkedHashMap中的尾部操作,在HashMap中并没有用到这个参数
接下来我们分析putVal的源码。

第一步:判断是否初始化了底层数组。
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
putVal第一段代码就是上面的代码,它首先将tab=table(这个table就是所说的底层的数组)并判断是否为null,同时判断tab的长度是否为0,只要两者有一个成立,就会进入n=(tab=resize()).length这句代码。在这一篇文章中我们分析了HashMap的构造方法,并没有一个构造方法对底层的数组进行初始化,所有的构造方法仅仅对加载因子或者扩容的阀门进行了初始化,底层数组初始化的工作放在了第一次调用put的时候,这个知识点大家一定要记住。因为这篇文章是介绍HashMap的put的,关于数组怎样进行初始化或者扩容的,我会有专门一篇文章详细讲解,这里就不再分精力阐述。只需记得put的第一步操作需要判断底层数组是否初始化了,如果没有初始化,就首先调用resize()进行初始化,如果已经初始化了,则继续执行下面的代码。通过这一步后,底层数组就变成了如下图示:

带你走进Java集合-HashMap源码-put方法的源码解析
第二步:通过hash算出key应该在数组table的下标
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
1:(n-1)&hash:就是获取key应该在数组的下标
2:tab[(n-1)&hash]:就是获取此下标数组的值,然后赋值给p,而p是一个Node,如果p==null,说明此下标还没有任何的值,所以直接把新插入的元素放到此处。
3:tab[i] = newNode(hash, key, value, null):就是把新插入的key,value封装成Node节点,然后放到数组中。
例如,我们map.put(“a”,3)到HashMap中,通过计算应该放到下标为1的地方,如图所示

带你走进Java集合-HashMap源码-put方法的源码解析
第三步:判断新插入的key和p.key是否相等
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
1:其中p=tab[(n-1)&hash]
2:判断新插入的key,和通过key计算的下标对应的key是否相等。
例如,我们map.put(“a”,5)到HashMap中,通过计算应该放到下标1的地方,而此时p=(“a”,3),那么p.hash=hash,p.key=key,所以会执行这一步。如图所示:

第四步:第三步不符合,接下来判断p是否为红黑树,如果是红黑树,那么按照红黑树的方式插入
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值