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 newValue;
            if ((newValue = mappingFunction.apply(key)) != null) { //新的value为null,则不会执行操作,即不会插入key
                put(key, newValue);
                return newValue;
            }
        }

        return v;
    }

putIfAbsent代码

 default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

查看它们的源码,可以比较清晰的了解两者的区别。

  • computeIfAbsent第二个参数接收的是一个函数式接口Function(在实际调用中通常使用lambda表达式或方法引用),函数输入是key,计算得到value。如果这个key不存在,则将计算得到的value进行插入,返回新的value。否则,返回原先的值。可以认为,返回的值就是执行此操作后的value值,无论是否进行了插入
  • putIfAbsent第二个参数直接接收value。如果对应的key不存在,将value插入,返回null。否则,不插入,返回原值。这里返回的值是原先的value值,如果key不存在,原先对应的value为null,自然就会返回null.
  • 以上内容在其他的文章中也有说明,不过除此之外我觉得还有一点需要强调的是,如果对应的key已经存在了,那么computeIfAbsent不会执行value表达式的方法,而putIfAbsent会执行。

一个简单的测试代码如下

public class Test {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.putIfAbsent("a", buildValue("a"));
        map.computeIfAbsent("b", key -> buildValue(key));
        System.out.println("========");
        map.putIfAbsent("a", buildValue("a"));
        map.computeIfAbsent("b", key -> buildValue(key));
    }

    private static String buildValue(String s) {
        System.out.println("build value: " + s);
        return s;
    }
}

输出

build value: a
build value: b
========
build value: a

可以看到,第二次调用putIfAbsent,尽管我们知道没有执行插入,但是仍然执行了buildValue方法,但是第二次调用computeIfAbsent,却没有触发buildValue方法。

其实根据源码也可以看出,putIfAbsent的value是作为方法参数进行传入的,所以不管是否插入都会执行计算得到value。而computeIfAbsent的value是在Function中的方法返回值,只有需要插入时才会执行(就是源码中mappingFunction.apply(key)这里)

你可能感兴趣的:(java,Map,computeIfAbsent,putIfAbsent)