computeIfAbsent 是 HashMap 的实用方法,用于键不存在时自动计算并存入新值,避免手动判空+put;接收 key 和 Function 两个参数,实现“有则取,无则算再存”。

computeIfAbsent 是 HashMap 提供的一个非常实用的方法,它能在键不存在时自动计算并放入新值,避免手动判空 + put 的冗余逻辑,让代码更简洁、线程安全(在单次调用内)、且不易出错。
核心作用:有则取,无则算再存
它接收两个参数:一个 key 和一个 Function super K, ? extends V> 类型的映射函数。执行逻辑是:
- 如果 key 已存在,直接返回对应 value(不触发函数)
- 如果 key 不存在,调用函数生成新值,将
(key, newValue)存入 map,并返回该新值 - 整个过程是原子性的(对单个 key 而言),无需额外同步
典型场景:构建嵌套结构(如 List 或 Set)
比如统计每个部门的员工列表,传统写法需要先 get 判空、new ArrayList、put 回去;用 computeIfAbsent 一行搞定:
Map<String, List<String>> deptToEmployees = new HashMap<>();
deptToEmployees.computeIfAbsent("研发部", k -> new ArrayList<>()).add("张三");
deptToEmployees.computeIfAbsent("研发部", k -> new ArrayList<>()).add("李四");
// 结果:{"研发部": ["张三", "李四"]}
注意:lambda 中的 k -> new ArrayList() 只在 key 第一次访问时执行,后续同 key 调用直接复用已存在的 list。
立即学习“Java免费学习笔记(深入)”;
替代 if-put-if-null 模式
以前常见写法:
if (!map.containsKey(key)) {
map.put(key, expensiveCalculation());
}
return map.get(key);
现在可简化为:
return map.computeIfAbsent(key, k -> expensiveCalculation());
不仅少写三行,还避免了两次哈希查找(containsKey + get),也防止多线程下重复计算(只要函数本身无副作用,结果就一致)。
注意事项和陷阱
- 函数不能返回
null,否则抛 NullPointerException - 函数应尽量轻量、无副作用;若内部修改了 map 自身,行为未定义
- 它只保证单 key 操作的原子性,不保护整个 map 的并发修改 —— 多线程高频更新仍需考虑
ConcurrentHashMap - 如果 value 类型是不可变对象(如 String、Integer),且计算开销小,也可以放心用


















