请求详解Java 8 Map中putIfAbsent与computeIfAbsent的差异
Java 8 Map中putIfAbsent和computeIfAbsent的核心区别
好问题!这两个方法都是Java 8为Map新增的便捷操作,乍看功能相似,但在执行逻辑、性能优化上有本质区别,我来给你详细拆解:
1. 核心逻辑差异
二者的目标都是「当指定Key不存在时往Map中添加元素」,但获取Value的时机和方式完全不同:
- putIfAbsent(K key, V value):你需要提前准备好Value,无论Map中是否存在该Key,这个Value都会被创建/获取。如果Key不存在,就将这个Value放入Map;如果Key已存在,直接返回Map中已有的Value,不会替换。
- computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction):你传入一个计算函数(通常用Lambda表达式),只有当Map中不存在该Key时,这个函数才会被执行,动态计算出对应的Value并放入Map;如果Key已存在,函数完全不会运行,直接返回Map中已有的Value。
2. 性能优化的关键场景:懒加载
这是二者最实用的区别,尤其针对获取Value成本较高的场景(比如查询数据库、调用远程API、读取大文件等):
- 用
putIfAbsent的话,哪怕Map里已经有对应的Key,你还是提前执行了获取Value的操作,白白浪费资源; - 用
computeIfAbsent则是「按需计算」,只有确认Key不存在时才会执行昂贵的获取逻辑,完美实现懒加载,避免不必要的性能开销。
3. 代码示例对比
用putIfAbsent的情况(可能浪费性能)
// 假设getArticleById是一个耗时的远程API调用 Article article = getArticleById(123); // 不管Map里有没有key=123,article已经被获取了 Article existingArticle = articleMap.putIfAbsent(123, article);
用computeIfAbsent的情况(懒加载优化)
// 只有当Map中没有123这个Key时,才会调用getArticleById(123) Article article = articleMap.computeIfAbsent(123, articleId -> getArticleById(articleId));
4. 额外细节补充
- Null值处理:
putIfAbsent允许传入null作为Value(取决于Map实现,比如HashMap支持),如果Key不存在,会将null放入Map;computeIfAbsent的计算函数如果返回null,不会往Map中插入任何元素(官方文档明确说明:如果函数返回null,不执行插入操作)。
- 返回值差异:
putIfAbsent返回的是Map中原来关联的Value(如果Key存在),否则返回null;computeIfAbsent返回的是最终关联的Value——要么是Map中原有的,要么是新计算出来的。
内容的提问来源于stack exchange,提问作者Adelin
相关产品推荐
相关产品推荐

