HashMap的奇幻漂流:当一个数组决定去整容

ops/2025/3/15 8:56:14/

标准答案(面试官最爱版)

HashMap实现原理

  1. 数据结构:数组+链表/红黑树(Java 8+)
  2. 算法>哈希算法(h = key.hashCode()) ^ (h >>> 16)
  3. 索引计算(n-1) & hash(n为数组长度)
  4. 冲突解决:链表→红黑树(阈值=8),树→链表(阈值=6)
  5. 扩容机制:2倍扩容,负载因子默认0.75

用程序员黑话:

“它就是个会变形的瑞士卷——平时是夹心饼干(数组+链表),吃撑了变千层蛋糕(红黑树)”


一、初入江湖:数组的容貌焦虑

1.1 基础人设:图书馆管理员

假设你有个16层的书架(数组),每层放着:

  • 空书架:等待书籍(Entry)入驻
  • 单本书:直接上架(没有哈希冲突)
  • 一摞书:链表结构(哈希碰撞时叠罗汉)
  • 精装书柜:红黑树形态(当书堆超过8本)
// 典型书架结构
[null,Node<K,V>,        // 单本书TreeNode<K,V>,    // 精装书柜LinkedList<Node> // 书堆
]

1.2 哈希函数:图书编号玄学

图书上架流程:

public int hashCode() {return 作者姓氏首字母.charCodeAt(0) * 31+ 书名首字母.charCodeAt(0); // 31是玄学质数
}

现实往往是:

  • 《百年孤独》和《白夜行》可能挤在同一层(哈希碰撞)
  • 管理员(HashMap)碎碎念:“都怪马尔克斯和东野圭吾姓氏首字母都是B!”

二、冲突解决:书架的生存战争

2.1 链表模式:叠罗汉的艺术

当新书到来时:

  1. 先按哈希值找楼层
  2. 如果该层已有书:
    • Java 7:新书放最上面(头插法)
    • Java 8:新书放最下面(尾插法)

为什么改尾插法?

答:为了防止多线程扩容时形成环形链表(曾经导致CPU 100%的惨案)

2.2 红黑树模式:卷王诞生

当某层书堆超过8本:

if (binCount >= TREEIFY_THRESHOLD - 1) {treeifyBin(tab, hash); // 呼叫变形金刚!
}

变形代价:

  1. 需要书架总层数≥64(MIN_TREEIFY_CAPACITY)
  2. 消耗CPU给书堆做美甲(树化操作)

降级机制:当书减少到6本时,变回普通书堆(防止频繁转换)


三、扩容风暴:图书馆扩建计划

3.1 触发条件:书架负载率超75%

if (size > threshold) {resize(); // 警报!需要扩建!
}

扩建流程:

  1. 新书架扩容2倍(16→32层)
  2. 旧书籍重新计算楼层:
    • 原楼层 或 原楼层+旧容量(二进制魔术)
    • 例如旧楼层=5(0101),新楼层=5或5+16=21

3.2 死亡遍历:多线程的噩梦

未同步的HashMap在扩容时:

  • 线程A正在搬书到新书架
  • 线程B突然来借书
  • 结果可能:拿到null、死循环、数据丢失

解决方案

用ConcurrentHashMap——给每个书架配保安(分段锁)


四、使用禁忌:程序员的防秃指南

4.1 自定义对象的坑

class Student {String name;// 忘记重写hashCode和equals...
}// 使用后果:
map.put(new Student("张三"), 90);
map.get(new Student("张三")); // 返回null(当场秃头)

4.2 负载因子调参玄学

  • 设0.9:节省内存但容易碰撞(书架挤成沙丁鱼罐头)
  • 设0.5:查询快但内存翻倍(每个书架只放半本书)

黄金建议:非必要别动默认0.75,这是数学家算出来的魔法数字


五、灵魂拷问:为什么不用二叉搜索树?

  1. 树化成本高:链表变树要旋转染色(美甲时间)
  2. 退化合订本:树节点占用内存是链表的2倍
  3. 小数据优势:链表在少量数据时遍历更快

用生活比喻:

整理5本书用书堆(链表)更快,整理50本书才需要书柜(红黑树)

请添加图片描述


http://www.ppmy.cn/ops/165896.html

相关文章

AI自动化、资本短视、三输与破局

当前AI应用中的一个深层矛盾&#xff1a;工程师使用AI将很专业的任务变成小白可以操作的工作&#xff0c;然后资本方给小白很少的钱把工程师裁掉了&#xff0c;然而小白不懂底层&#xff0c;出问题几乎无法修复。由此&#xff0c;技术普及与专业能力之间的断层引发了"三输…

扫描电子显微镜有何特点和用途?

扫描电子显微镜&#xff08;SEM&#xff09;是一种重要的材料分析仪器&#xff0c;具有以下特点和用途&#xff1a; 一、特点 &#xff08;1&#xff09;高分辨率&#xff1a;能够提供较高的分辨率&#xff0c;一般可达纳米级别&#xff0c;场发射扫描电子显微镜的分辨率甚至…

Flutter 常用控件大全:从入门到实战,全面掌握 UI 开发

本文详细整理了 Flutter 中 50 常用控件&#xff0c;涵盖文本、布局、按钮、列表、动画等核心组件。每个控件均附有 属性说明 和 实战代码示例&#xff0c;帮助你快速掌握 Flutter UI 开发的精髓。无论你是初学者还是进阶开发者&#xff0c;本文都能为你提供实用的参考和指导&a…

韦伯望远镜的拉格朗日点计算推导过程,包含MATLAB和python运动轨迹仿真代码

研究过程 起源与提出&#xff1a;1687 年牛顿提出 “三体问题”&#xff0c;旨在研究三个可视为质点的天体在相互之间万有引力作用下的运动规律&#xff0c;但因运动方程过于复杂&#xff0c;难以得到完全解。欧拉的贡献1&#xff1a;1767 年&#xff0c;瑞士数学家莱昂哈德・…

笔试刷题专题(一)

文章目录 最小花费爬楼梯&#xff08;动态规划&#xff09;题解代码 数组中两个字符串的最小距离&#xff08;贪心&#xff08;dp&#xff09;&#xff09;题解代码 点击消除题解代码 最小花费爬楼梯&#xff08;动态规划&#xff09; 题目链接 题解 1. 状态表示&#xff1…

Python数据类型进阶——详解

—— 小 峰 编 程 目录 1.整型 1.1 定义 1.2 独有功能 1.3 公共功能 1.4 转换 1.5 其他 1.5.1 长整型 1.5.2 地板除(除法&#xff09; 2. 布尔类型 2.1 定义 2.2 独有功能 2.3 公共功能 2.4 转换 2.5 其他 做条件自动转换 3.字符串类型 3.1 定义 3.2 独有功能…

谷歌Chrome或微软Edge浏览器修改网页任意内容

在谷歌或微软浏览器按F12&#xff0c;打开开发者工具&#xff0c;切换到console选项卡&#xff1a; 在下面的输入行输入下面的命令回车&#xff1a; document.body.contentEditable"true"效果如下&#xff1a;

宇树与智元的崛起:机器人“灵魂”注入的技术密码

目录 机器人运动的基石&#xff1a;大扭矩与平衡术 大扭矩&#xff1a;力量的源泉 平衡术&#xff1a;动态平衡的艺术 从运动到智能&#xff1a;AI学习的“灵魂”注入 强化学习&#xff1a;试错中的成长 模仿学习&#xff1a;站在巨人的肩膀上 数据与知识共享&#xff1…