put方法主要干这几件事情:
1.算出key的hash值,key的hashcode的高低位异或算出来。
2.若果散列表为空,则初始化散列表。
3.算出散列表下标位置,(n - 1) & hash。
4.散列表下标位置值为空,则把传入的参数封装成node节点设置到散列表下标位置。
5.如果该散列表下标的值不为空,如果key和hash值与传入的值相等,则直接覆盖,如果散列表下标的节点是红黑树,则走红黑树的逻辑,相等则覆盖,不相等,则插入,具体红黑树逻辑后面会讲解。
6.如果当前散列表下标的值与传入的值不相等,又不是红黑树,则判断该下标的节点next是否为空,如果为空直接把传入的参数封装成node节点插入到该散列表下标值后面,然后判断链表元素个数是否超过8,超过则走树化的逻辑,没超过则break,修改次数modCount加1,元素个数加1,然后判断散列表元素个数是否超过扩容阈值,超过则扩容。
7.如果是链表,已经发生过hash冲突了,则循环这个链表,key,hash值相等则覆盖,不相等则插入,插入完以后再次判断是否达到树化条件,没有达到树化条件,break,修改次数modCount加1,元素个数加1,然后判断散列表元素个数是否超过扩容阈值,超过则扩容.

 下面看具体的源码。

1.put方法入口如下图所示,先算key的hash值,再调用putVal方法进行put操作。

2.看下hash(key)方法。key的hashcode,高低位异或运算。key==null 返回0,说明null是插入在散列表下标第0个位置。

3.得到完key的hash以后返回进入putVal方法。该方法主要就是处理散列表初始化,key,value的插入覆盖,但分链表,红黑树,和没有hash冲突的情况。下面一个一个看吧。首先刚进入该方法,我们要判断一下该散列表是否为null或者散列表的length是否等于0,如果是则调用resize初始化散列表。具体resize初始化逻辑,可以看下上一篇文章。散列表不为空,算出散列表下标位置((n - 1) & hash),如果该下标位置node节点为null,则把参数封装成node节点插入该下标位置。

4.如果该散列表下标的值不为空。那么就先判断与传入的hash,key是否相等,如果相等则覆盖,如果不相等,则判断该下标元素node是否是红黑树,如果是红黑树则走红黑树的逻辑(红黑树后面单独讲),如果不满足红黑树的条件,那就是链表的场景了。

看下链表的场景,如果该散列表下标node的next为空,则把传入的参数封装成node,设到该下标node的后面。设完以后,判断是否达到树化条件,达到了就树化,break跳出循环,修改次数加1,散列表元素个数size加1.接着如果是本来已经有hash冲突的情况,则链表已经生成,循环该链表,如果key,hash相等则覆盖,不相等则插入,插入完一样判断树化条件,修改次数加1,散列表元素个数size加1,然后判断散列表元素个数是否超过扩容阈值,超过则扩容。

 

posted on   路飞_lufei  阅读(134)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!



点击右上角即可分享
微信分享提示