putifabsent 和 computeifabsent 均在键不存在时插入,但返回值语义不同:前者返回插入前旧值(不存在则返 null),后者返回当前关联值(存在返旧值,不存在则计算并返新值);前者需预构造值,后者惰性计算,更省资源;前者将 value 为 null 视为 absent,后者仅依据 key 是否存在判断。

putIfAbsent 和 computeIfAbsent 都用于“键不存在时才插入”,但返回值语义不同,直接影响你后续逻辑是否需二次查值、是否要避免构造开销,选哪个关键看两点:要不要延迟计算值、要不要用返回值做判断。
返回值含义完全不同
两者都只在 key 不存在时插入,但返回什么有本质区别:
-
putIfAbsent(key, value):返回的是 插入前已存在的值;key 不存在就插入并返回
null;key 存在就啥也不干,返回旧值。 - computeIfAbsent(key, mappingFunction):返回的是 当前与 key 关联的值——无论 key 原来是否存在。key 存在 → 返回旧值;key 不存在 → 计算新值、插入、返回这个新值。
值的创建时机决定资源开销
如果你传的 value 构造成本高(比如 new ArrayList()、解析大 JSON、IO 调用),选错方法会白耗资源:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- putIfAbsent 要求你提前准备好 value 对象,哪怕 key 已存在也会先 new 出来再丢弃——内存和 GC 压力可能不小。
- computeIfAbsent 的 mappingFunction 只在 key 真的缺失时才执行,天然惰性,适合昂贵计算或依赖 key 的动态生成场景。
对 null 值的处理逻辑不同
二者对 “key 存在但 value 为 null” 的判定也不同:
-
putIfAbsent 把
map.get(key) == null就当作“absent”,所以如果 key 映射到null,它仍会覆盖插入新值。 -
computeIfAbsent 严格按
!map.containsKey(key)判断,即使 key 映射到null,它也认为“存在”,不会触发函数调用,也不会覆盖。
实际选型建议
按典型场景快速决策:
- 想插入一个固定常量(如
"default"),且后续只关心“是否首次插入”,用 putIfAbsent ——简洁直接。 - 值需要根据 key 动态计算(如
k -> loadFromDB(k))、或对象构造开销大、或需保证线程安全插入(尤其在ConcurrentHashMap中),选 computeIfAbsent。 - 需要靠返回值做分支逻辑(比如“若首次插入则发通知”),注意:putIfAbsent 返回
null表示插入成功,computeIfAbsent 返回非null不代表是新值——得结合containsKey或额外标志判断。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










