Map.computeIfPresent()仅在键存在且值非null时执行remapping函数,返回null则删除该键,否则更新值;不插入新键,适用于安全累加、校验更新等场景。

Map.computeIfPresent() 的核心作用就是:当且仅当指定键已存在且关联值非 null(对非 null 值的 Map)时,才用给定的 remapping 函数更新该键的值。它天然适合“键存在才执行”的场景,避免手动判空和重复查表。
明确触发条件:键必须存在 + 值不能为 null
该方法不会插入新键,也不会处理键不存在或值为 null 的情况。它内部等价于:
- 先调用
map.containsKey(key) - 再获取当前值
v = map.get(key) - 仅当
v != null(对 HashMap/ConcurrentHashMap 等默认实现)时,才执行你的函数remappingFunction.apply(key, v) - 若函数返回
null,则该键会被自动移除(这是它的副作用,需留意)
典型业务逻辑:安全地累加、转换或校验后更新
比如统计用户订单数,只在用户已注册(键存在)时才 +1;或对已有配置项做格式校验后再更新:
Map<String, Integer> orderCount = new HashMap<>();
orderCount.put("user123", 5);
// ✅ 仅当 user123 存在时,才将其订单数 +1
orderCount.computeIfPresent("user123", (key, oldValue) -> oldValue + 1);
// ❌ 若传入 "user456"(不存在),什么都不会发生,orderCount 不变
orderCount.computeIfPresent("user456", (key, oldValue) -> oldValue + 1); // 无效果
注意返回值语义:null 表示删除,非 null 才是更新
你的 lambda 返回值直接决定后续行为:
- 返回非
null值 → 替换原值 - 返回
null→ 删除该键(相当于map.remove(key))
例如,只允许订单数 ≤ 10 的用户继续下单,超限就冻结(移除记录):
orderCount.computeIfPresent("user123", (key, count) -> {
int next = count + 1;
return next <= 10 ? next : null; // 超限则删键
});
与 computeIfAbsent / compute 的关键区别
别混淆三者用途:
-
computeIfPresent:键存在且值非 null → 更新或删键 -
computeIfAbsent:键不存在 → 插入新值(常用于懒加载缓存) -
compute:无论键是否存在 → 都执行函数(更通用,但需自己判断 oldVal 是否为 null)
当你明确只要“已有数据才动”,computeIfPresent 最简洁、意图最清晰,也比先 get() 再 put() 更原子(尤其在并发 Map 中)。

















