Java Map 接口中的 computeIfAbsent 和 putIfAbsent 方法

前言

在Java 8中,Map接口引入了一些新的默认方法,这些方法极大地增强了Map的功能。其中,computeIfAbsentputIfAbsent是用于处理缺失键值对的两种常用方法。它们在某些情况下可以避免常见的并发问题,提高代码的效率和可读性。

putIfAbsent 方法

putIfAbsent方法用于在Map中只有在指定键不存在时才插入指定的值。它不会覆盖已经存在的键对应的值。

示例代码如下:

import java.util.HashMap;
import java.util.Map;

public class PutIfAbsentExample {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("key1", "value1");

        // 使用 putIfAbsent 插入值
        // 由于 "key1" 已经存在,所以不会插入 "newValue1"
        map.putIfAbsent("key1", "newValue1"); 
        // "key2" 不存在,所以插入 "value2"
        map.putIfAbsent("key2", "value2");
 		// 输出: {key1=value1, key2=value2}
        System.out.println(map);
    }
}

源码剖析

我们来看一下putIfAbsent方法的JDK源码(以HashMap为例):

public V putIfAbsent(K key, V value) {
    Node<K,V> e;
    if ((e = getNode(hash(key), key)) == null) {
        e = putVal(hash(key), key, value, true, true);
    }
    return e == null ? null : e.value;
}

在这个方法中,首先使用getNode方法检查给定键是否已经存在于Map中。如果不存在,就调用putVal方法插入新的键值对。

computeIfAbsent 方法

computeIfAbsent方法用于在Map中如果指定的键不存在,则使用给定的映射函数计算其值,并将该值插入Map中。与putIfAbsent不同的是,computeIfAbsent能够动态计算要插入的值。

示例代码如下:

import java.util.HashMap;
import java.util.Map;

public class ComputeIfAbsentExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();

        // 使用 computeIfAbsent 动态计算值
        map.computeIfAbsent("key1", k -> k.length());
        map.computeIfAbsent("key2", k -> k.length());
		// 输出: {key1=4, key2=4}
        System.out.println(map);
    }
}

源码分析

public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
    if (mappingFunction == null)
        throw new NullPointerException();
    int hash = hash(key);
    Node<K,V> e;
    V oldValue;
    if ((e = getNode(hash, key)) == null) {
        V v;
        if ((v = mappingFunction.apply(key)) != null) {
            e = putVal(hash, key, v, false, true);
        }
    }
    return e == null ? null : e.value;
}

在computeIfAbsent中,如果给定键不存在,则通过映射函数mappingFunction计算新值,并调用putVal方法将其插入Map。

两者的区别

功能差异:

  • putIfAbsent仅在键不存在时插入给定的值。computeIfAbsent在键不存在时通过一个映射函数计算并插入新值。

使用场景:

  • 当你有一个确定的默认值并希望在键缺失时插入时,使用putIfAbsent。当值需要根据键动态计算时,使用computeIfAbsent。

性能:

  • computeIfAbsent由于需要执行映射函数,可能会略慢于putIfAbsent,但在需要动态计算值的场景下,这是必需的。

在Java的开发过程中,合理选择putIfAbsent和computeIfAbsent可以简化代码逻辑,减少错误。它们帮助开发者更方便地处理缺失值的情况,特别是在需要考虑并发和性能时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值