computeIfAbsent和putIfAbsent的区别(value表达式是否执行)& key存在时也可能插入?

computeIfAbsent是java8的新方法,它定义在Map接口中,和我们常用的putIfAbsent有着类似的功能,都是在map不存在某个key的时候(其实还有一种情况,key存在,但是对应的value为null,从下面的源码也可以看出),进行插入

computeIfAbsent代码

  default V computeIfAbsent(K key,
            Function<? super K, ? extends V> mappingFunction) {
   
        Objects.requireNonNull(mappingFunction);
        V v;
        if ((v = get(key)) == null) {
    //这里if为true的情况包括了key不存在和key对应的value为null,下同
            V<
### Java Map `computeIfAbsent` vs `putIfAbsent`: 使用场景与差异 #### 方法定义 `computeIfAbsent` `putIfAbsent` 是 Java `Map` 接口中提供的两个条件插入方法。两者的功能虽然都涉及向 `Map` 插入键值对,但在具体行为上有显著的区别。 - **`putIfAbsent(K key, V value)`**: 尝试将指定的值与指定的键关联,但仅当该键未映射到任何值执行此操作[^2]。 ```java default V putIfAbsent(K key, V value) { V v = get(key); if (v == null) { v = put(key, value); } return v; } ``` - **`computeIfAbsent(K key, Function&lt;? super K, ? extends V&gt; mappingFunction)`**: 如果指定的键尚未存在于 `Map` 或其对应的值为 `null`,则通过给定的函数计算新值并将其插入到 `Map` 中。 ```java default V computeIfAbsent(K key, Function&lt;? super K, ? extends V&gt; mappingFunction) { Objects.requireNonNull(mappingFunction); V v; if ((v = get(key)) == null) { V newValue = mappingFunction.apply(key); if (newValue != null) { put(key, newValue); return newValue; } } return v; } ``` --- #### 主要区别 1. **参数形式** - `putIfAbsent` 只接受固定的键 (`K`) (`V`) 参数。 - `computeIfAbsent` 则允许传入一个动态生成值的函数 (`Function&lt;K, V&gt;`)。 2. **灵活性** - `putIfAbsent` 更适合于简单的情况,即只需要判断是否存在某个键,并在不存在的情况下插入固定值。 - `computeIfAbsent` 提供了更高的灵活性,因为它可以通过传递的函数动态生成值。 3. **线程安全性** - 在多线程环境下,`ConcurrentHashMap.putIfAbsent` 是原子性的,因此可以直接安全使用[^4]。 - 同样地,`ConcurrentHashMap.computeIfAbsent` 也提供了线程安全保障,但由于它可能调用外部函数来生成值,因此需要注意函数本身的线程安全性。 4. **性能开销** - 对于简单的插入操作,`putIfAbsent` 的性能通常优于 `computeIfAbsent`,因为后者需要额外的间来调用函数生成值。 5. **返回值语义** - `putIfAbsent` 返回的是当前已存在的值(如果有),或者是 `null` 表示之前没有对应值。 - `computeIfAbsent` 返回的是最终存储到 `Map` 中的值,可能是由函数生成的新值,也可能就是原本就有的旧值。 --- #### 示例代码 ##### 使用 `putIfAbsent` 适用于静态值插入: ```java import java.util.HashMap; public class PutIfAbsentExample { public static void main(String[] args) { HashMap&lt;String, String&gt; map = new HashMap&lt;&gt;(); // 插入键值对 System.out.println(map.putIfAbsent(&quot;key&quot;, &quot;value&quot;)); // 输出: null // 键已经存在不修改原值 System.out.println(map.putIfAbsent(&quot;key&quot;, &quot;new_value&quot;)); // 输出: value } } ``` ##### 使用 `computeIfAbsent` 适用于动态值生成: ```java import java.util.concurrent.ConcurrentHashMap; public class ComputeIfAbsentExample { public static void main(String[] args) { ConcurrentHashMap&lt;Integer, Integer&gt; map = new ConcurrentHashMap&lt;&gt;(); // 动态生成值 int result = map.computeIfAbsent(1, k -&gt; k * 10); System.out.println(result); // 输出: 10 // 已经存在的键不会重新计算 result = map.computeIfAbsent(1, k -&gt; k * 20); System.out.println(result); // 输出: 10 } } ``` --- #### 总结 `putIfAbsent` `computeIfAbsent` 虽然都能实现有条件的插入操作,但适用场景不同。前者更适合处理简单的、不需要复杂逻辑的操作;而后者由于支持动态值生成,在更复杂的业务需求下显得更加灵活强大。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值