map.computeIfAbsent()
和 map.putIfAbsent()
都是 java.util.Map
接口提供的方法,用于处理键值对的插入操作。它们在功能上有相似之处,但也有一些重要的区别。下面详细解释这两个方法的异同:
map.putIfAbsent(K key, V value)
- 功能:如果指定的键尚未关联到任何值(或者映射到
null
),则尝试将指定的值与此键关联。 - 返回值:返回与指定键关联的前一个值,如果没有前一个值,则返回
null
。 - 线程安全:在多线程环境中,需要外部同步来保证线程安全。
- 示例:
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
Integer oldValue = map.putIfAbsent("apple", 2); // 返回 1
Integer newValue = map.putIfAbsent("banana", 3); // 返回 null
map.computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
不同点
- 功能:如果指定的键尚未关联到任何值(或者映射到
null
),则尝试使用给定的函数计算一个值,并将该值与此键关联。 - 返回值:返回与指定键关联的当前值(可能是新计算的值)。
- 线程安全:在多线程环境中,需要外部同步来保证线程安全。
- 示例:
Map<String, List<String>> map = new HashMap<>(); List<String> list = map.computeIfAbsent("apple", k -> new ArrayList<>()); list.add("red"); List<String> list2 = map.computeIfAbsent("banana", k -> new ArrayList<>()); list2.add("yellow");
异同点
相同点
- 目的:两者都用于在键不存在时插入值。
- 线程安全:两者都需要外部同步来保证多线程环境下的线程安全。
-
值的提供方式:
putIfAbsent
直接提供一个具体的值。computeIfAbsent
提供一个函数,该函数在键不存在时被调用以计算值。
-
返回值:
putIfAbsent
返回与指定键关联的前一个值,如果没有前一个值,则返回null
。computeIfAbsent
返回与指定键关联的当前值(可能是新计算的值)。
-
延迟计算:
putIfAbsent
在调用时立即确定值。computeIfAbsent
在调用时只传递函数,只有在键不存在时才会调用该函数来计算值,这可以避免不必要的计算。
示例对比
putIfAbsent
示例
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
// 尝试插入 "apple" 的值 2,但由于 "apple" 已经存在,不会插入
Integer oldValue = map.putIfAbsent("apple", 2); // 返回 1
System.out.println(oldValue); // 输出 1
// 尝试插入 "banana" 的值 3,由于 "banana" 不存在,会插入
Integer newValue = map.putIfAbsent("banana", 3); // 返回 null
System.out.println(newValue); // 输出 null
computeIfAbsent
示例
Map<String, List<String>> map = new HashMap<>();
// 尝试插入 "apple" 的值,由于 "apple" 不存在,会调用函数创建一个新的列表
List<String> list = map.computeIfAbsent("apple", k -> new ArrayList<>());
list.add("red");
// 尝试插入 "banana" 的值,由于 "banana" 不存在,会调用函数创建一个新的列表
List<String> list2 = map.computeIfAbsent("banana", k -> new ArrayList<>());
list2.add("yellow");
System.out.println(map); // 输出 {apple=[red], banana=[yellow]}
总结
putIfAbsent
:适用于已知要插入的具体值的情况。computeIfAbsent
:适用于需要在键不存在时动态计算值的情况,可以避免不必要的计算。