HashMap基础
-
底层数据结构,1.7和1.8有什么区别
1.7:数组+链表
1.8:数组+(链表 | 红黑树) -
为什么要用红黑树
当链表过长时查询效率太低,树化可以提高查询效率 -
为什么不是一开始就用树,而是达到一定条件再树化
TreeNode占用空间比普通链表占用空间大 -
树化阈值为何是8
为了让树化概率更小,因为正常情况下链表长度达到8几乎是没有的 -
何时会树化
链表长度达到8且数组长度达到64 -
何时为退化为链表
- 数组扩容后拆分树时,如果树元素个数<=6,则会退化为链表
- 删除树元素时,如果删除之前树的根节点、左孩子、右孩子或左孙子之一有一个为null,则会退化为链表。
-
索引如何计算
根据对象的hashCode()方法得到对象的hash值,再调用HashMap的hash()方法进行二次hash,用二次hash的值对数组大小取模的结果即为索引值。但取模的操作可实际为:hash & (数组大小 - 1);与运算效率更高。 -
已经有了hashCode()为何还要提供hash()方法?
二次hash是为了综合高位数据,使哈希分布更均匀。 -
数组容量为何是2的n次幂
容量为2的n次幂时取模运算可以替换为与运算,效率更高 -
put()方法流程,1.7与1.8有何不同
HashMap是懒惰创建数组的,首次使用才创建数组
1 计算桶下标,即数组索引
2 如果该索引处为空,则创建Node占位返回
3 如果索引处不为空
3.1 如果已经为TreeNode,走红黑树的添加或更新逻辑
3.2 如果是普通Node,走链表的添加或更新逻辑,如果链表长度超过阈值,走树化逻辑
4 返回前检查是否超过数组阈值,超过就进行扩容,每次扩容为原来的2倍1.7与1.8的不同
(1) 插入到链表时,1.7为头插法,1.8是尾插法
(2) 1.8是大于阈值直接扩容,1.7是大于阈值且没有空位时才扩容
(3) 1.8在扩容计算node索引时会优化 -
加载因子为什么默认0.75f
为了扩容不太频繁且链表不会太长,在空间占用与查询效率之间取得较好的权衡
当加载因子太小,就会导致频繁扩容
当加载因子太大,就会导致扩容不及时,链表过长
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤