hashmap的putval方法执行流程为:先初始化数组并计算key哈希值,再通过(n-1)&hash定位桶位置;若桶空则直接插入,否则比较hash与key决定更新或遍历链表/红黑树;链表长度≥8且数组≥64时树化;最后更新值或扩容并返回旧值/null。

HashMap 的 putVal 方法是整个 put 操作的核心实现,它决定了键值对如何被定位、插入、更新或树化。分析它的执行流程,关键在于抓住“初始化→定位→冲突处理→后续动作”这条主线,而不是死记代码顺序。
哈希计算与数组初始化
方法一开始会检查内部数组 table 是否为空或长度为 0。如果是(比如刚 new 出来还没 put 过),就调用 resize() 初始化数组,默认容量为 16。同时,会对 key 计算哈希值:
– 若 key 为 null,hash 固定为 0;
– 否则调用 key.hashCode(),再做扰动: (h = key.hashCode()) ^ (h >>> 16)。
这个扰动是为了让高 16 位也参与索引计算,避免低位相似导致大量碰撞。
桶位置计算与首节点判断
用公式 i = (n - 1) & hash 算出数组下标(n 是 table 长度,必须是 2 的幂)。这比取模快,且能均匀分布。
拿到下标 i 后,取出 tab[i](即该桶的头节点 p):
– 如果 p 为 null,说明桶空,直接新建 Node 放进去;
– 如果 p 不为 null,就要比对:先看 hash 值是否相等,再用 == 或 equals() 判断 key 是否相同。匹配就准备更新值。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
链表与红黑树的分支处理
若首节点不匹配,就进入冲突处理分支:
– 如果 p 是 TreeNode,走红黑树的 putTreeVal 插入逻辑;
– 如果是普通 Node(链表),就遍历 next 链:
• 遍历时用 binCount 计数(从 0 开始,每跳一次 +1);
• 找到相同 key 就终止;没找到就插到链表尾;
• 插完后若 binCount >= 7(即链表已有 8 个节点),触发 treeifyBin 尝试树化(前提是数组长度 ≥ 64)。
更新、扩容与返回值
只要找到已有 key 对应的节点 e,就会更新其 value,并返回旧值。
如果新增了节点(非覆盖),会执行 size++,然后判断是否需要扩容:
– 当前元素总数 > 容量 × 加载因子(默认 0.75)时,触发 resize()。
最后返回旧值(存在时)或 null(新插入时)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










