HashMap相关问题
终于读了一次HashMap的源码,没有总结很好,稍作记录,对应的源码在
https://www.cnblogs.com/SunArmy/p/14678884.html 可自行去看
其他相关的两个博客非常不错(比我总结的强多多了),值得推荐
https://www.cnblogs.com/zengcongcong/p/11295349.html
https://blog.csdn.net/weixin_50666791/article/details/108731408
1、初识容量:1 << 4 (16,必须是2的幂)
2、最大容量:如果有参构造指定了更高的值,必须是2的幂,并且小于 1<<30
3、默认负载因子:0.75 (不指定的情况下默认0.75)
4、数据结构变红黑树的转换阀值:8(为存储箱使用树而不是列表的存储箱计数阈值。将元素添加到至少有这么多节点的容器时,容器将转换为树。该值必须大于2,并且至少应为8,以便与树移除中有关转换回普通箱的假设相匹配)
5、数据结构变数据转链表的阀值:6(在调整大小操作期间取消搜索(拆分)存储箱的存储箱计数阈值。应小于8目,且最多6目,用收缩检测下去除。)
6、最小树容量:64(可以树化存储箱的最小表容量(否则,如果存储箱中的节点太多,则会调整表的大小)应至少为4个树化阈值,以避免调整大小和树化阈值之间的冲突。)
7、HashMap数据结构:数组加链表,数组存储的就是每个链表的第一个元素,当一个put一个键值对的时候,会根据hash和(tab.length-1)做与运算去数组上寻址,如果 hash相同就会占用一个位置,它们就成为链表,需要注意的是1.8开始,当链表长度超过阀值8时链表就会被改造成树
8、允许null键和null值、非同步、线程不安全、
9、put方法(链表怎么插入,红黑树怎么插入,链表怎么转红黑树)?
1)key做hash,调用putVal方法,
2)首次先初始化table,然后在判断hash碰撞((length-1)&hash求数组下标),没有就直接插入)
3)有hash碰撞,判断key的值,一样的话直接新值替换旧值
4)key不一样继续往下判断是否是红黑树结构,如果是就直接调用红黑树的插入方法
5)如果是链表结构,循环找下一个节点,是null的话就直接新建(插入之后判断长度是否大于等于8,转红黑树),如果key相同新值换旧值
6)最后对整个长度做判断,是否大于阀值,决定是否扩容
10、remove方法(链表怎么删除的、红黑树怎么删除的)remove(Object key)
1)对key做hash,然后调用removeNode方法
2)找到对应的bucket
3)如果key相同则直接删除该节点
4)不相同就判断该bucket的结构是不是红黑树,是红黑树就根据红黑树的getTreeNode方法hash和key找到对应节点去删除
5)如果是链表就循环向下找节点,直到找到key相同的节点,然后删除
11、resize(方法,怎么扩容的)
1)先对数组进行扩容
2)将老数组copy到新数组中
3)如果是红黑树,调用红黑树的split方法
4)copy链表中的节点(根据原来hash和原数组length做与运算,0就放在新数组的前一半,1就放在新数组的后一半)
5)额外说明:
1、为什么put的时候是和length做与运算(16和32举例):因为length是2的幂(二进制只有最高位一个1其他位全是0),最后的结果只会是0或1,如果是1,说明hash对应length的最高位是1,那么范围应该是在16~31之间,如果是0那么最高位是0,只剩下了4个1,范围就是0~15
12、get方法(怎么去查找对应的值)
1)对key做hash,然后和(length-1)做与运算找到对应的bucket
2)比较key是否相同,相同直接返回,否则继续向下
3)如果是红黑树则调用红黑树的getTreeNode方法
4)遍历向下找key相同的mapping
13、红黑树怎么插入的?
1)获取跟节点(roots方法,向上遍历找parent,直到父节点为null,则该节点就是跟节点)
2)如果该节点的hash比插入的hash大就向左节点遍历向下,如果比插入的小就向右节点遍历向下,直到找到的节点没有子节点为止,把新节点添加到该节点下(根据dir插入左或者右)
3)如hash相同,并且key的地址或者equals相同,直接返回该节点
4)如hash相同,key不同;key没有实现Comparable接口或者实现了Comparable接口但是当前key的calss和父节点的key的class不一样,分别从左边的节点和右边的节点开始找对应的节点,如果找到了就直接返回该节点。否则就继续3)的过程(其实就是一直向下遍历)
14、链表怎么转红黑树
1)treeifyBin(tab,hash)方法,判断tab长度是否不足64,不足64只扩容不转红黑树
2)将所有的链表节点全部转成红黑树节点
3)将红黑树节点转成红黑树结构treeify(tab),这个方法和putTreeNode方法很像,就是遍历整个链表,根据hash重新计算位置
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库