HashMap的put()方法源码剖析

发布于:2022-10-22 ⋅ 阅读:(352) ⋅ 点赞:(0)

1.找到key对应的数组下标位置

如何找到key对应的数组下标位置?

①put (get同理) 的时候会调hash()获取key的哈希值

②先调key元素所属类的hashCode()方法得到hashCode值,再对hashCode进行位异或运算,得到hash值

③再对hash值进行位与运算,i = (n - 1) & hash 得到最终数组下标

 

2.比较

PS:常把数组中的每 一个节点称为一个桶

第一次添加元素时)若table未初始化(为null)或者长度为0,调用 resize 进行扩容

情况①若桶为空,即无发生碰撞

新生成结点放入桶中(数组 (n - 1) & hash 位置中)

  

情况②若桶中已经存在元素,即发生了哈希碰撞,则需要处理冲突,并进行判重比较

①与桶中第一个元素(即数组下标处的元素)进行比较

判重操作首先判断两个元素的hash值是否相等,不相等说明不是同一个元素,

                        相等则需要进行进一步判断,调用元素的equals方法进行判重。

若与桶中第一个元素相同,替换已存在元素的value

不同,则继续比较👇

②判断该桶是否使用红黑树处理冲突,即判断 数组下标处的元素是不是与TreeNode是同一类

若是红黑树,则调putTreeVal(),遍历红黑树,

                                                    若红黑树中存在与插入元素相同的元素,则返回已存在元素,

                                                    并替换已存在元素的value

                                                    若红黑树中不存在与插入元素相同的元素,则返回null

                                                    将插入元素插入红黑树,最后判断数组是否需要扩容

若不是红黑树,则进行👇

③遍历比较桶中链式存储的元素

 

链表中下一个元素进行比较,若不存在元素,则在尾部插入新结点

                      插入尾部之后,判断链表元素是否超过8个,若超过8个,则视情况转为红黑树

                      treeifBin()方法会判断,数组容量是否超过64,小于64,则对数组进行扩容

                                                                                          大于64,则将对应位置的链表转为红黑树

                        最后判断数组是否需要扩容

                 

                                        若存在元素,则与其进行比较,先比较hash值再比较equals

                                        若相同,则跳出循环,替换已存在元素的value

                                        若不相同,则继续比较链表的下一个元素,直至添加到链表尾部

注意点:只要是成功添加新元素(数组新桶、链表、红黑树中插入新元素)都会触发size的增加,和扩容的判断。并不是只有数组新格子(桶)被插入才会触发,链表、红黑树被插入也会触发。

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到