HashMap基础

  • 底层数据结构,1.7和1.8有什么区别
    1.7:数组+链表
    1.8:数组+(链表 | 红黑树)

  • 为什么要用红黑树
    当链表过长时查询效率太低,树化可以提高查询效率

  • 为什么不是一开始就用树,而是达到一定条件再树化
    TreeNode占用空间比普通链表占用空间大

  • 树化阈值为何是8
    为了让树化概率更小,因为正常情况下链表长度达到8几乎是没有的

  • 何时会树化
    链表长度达到8且数组长度达到64

  • 何时为退化为链表

    1. 数组扩容后拆分树时,如果树元素个数<=6,则会退化为链表
    2. 删除树元素时,如果删除之前树的根节点、左孩子、右孩子或左孙子之一有一个为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
    为了扩容不太频繁且链表不会太长,在空间占用与查询效率之间取得较好的权衡
    当加载因子太小,就会导致频繁扩容
    当加载因子太大,就会导致扩容不及时,链表过长

posted @   程长新  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
点击右上角即可分享
微信分享提示