Java8常用示例

java.util.Map中的putIfAbsent、computeIfAbsent、computeIfPresent、compute的区别

探索Java8:(三)Predicate接口的使用

HashMap

putIfAbsent

default V putIfAbsent(K key,V value)

If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value

上面是官方的解释,意思是如果给定的key不存在(或者key对应的value为null),关联给定的key和给定的value,并返回null;

如果存在,返回当前值(不会把value放进去);

     Map> map = new HashMap<>();
        map.put(2, Lists.newArrayList(22));
        List xx = map.putIfAbsent(2, Lists.newArrayList(1));
        System.out.println(map + " " + xx);//返回:{2=[22]} [22]

        map.clear();
        xx = map.putIfAbsent(1, Lists.newArrayList(1));
        System.out.println(map + " " + xx);//返回:{1=[1]} null

computeIfAbsent

default V computeIfAbsent(K key, Function mappingFunction)
If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.

If the function returns null no mapping is recorded. If the function itself throws an (unchecked) exception, the exception is rethrown, and no mapping is recorded. The most common usage is to construct a new object serving as an initial mapped value or memoized result, as in:

map.computeIfAbsent(key, k -> new Value(f(k)));
Or to implement a multi-value map, Map>, supporting multiple values per key:

map.computeIfAbsent(key, k -> new HashSet()).add(v);

官方文档的解释:如果给定的key不存在(或者key对应的value为null),就去计算mappingFunction的值;

如果mappingFunction的值不为null,就把key=value放进去;
如果mappingFunction的值为null,就不会记录该映射关系,返回值为null;
如果计算mappingFunction的值的过程出现异常,再次抛出异常,不记录映射关系,返回null;
如果存在该key,并且key对应的value不为null,返回null;(HashMap返回的是旧value)

     Map> map = new HashMap<>();
        map.put(2, Lists.newArrayList(22));
        List xx = map.computeIfAbsent(2, k -> new ArrayList<>());
        System.out.println(map + " " + xx);//返回:{2=[22]} [22] key存在,得到旧值并返回
        xx.add(222);
        System.out.println(map + " " + xx);//返回:{2=[22, 222]} [22, 222]

        map.clear();
        xx = map.computeIfAbsent(1, k -> new ArrayList<>());
        System.out.println(map + " " + xx);//返回:{1=[]} [] key不存在,计算后面的表达式并返回
        xx.add(1);
        System.out.println(map + " " + xx);//返回:{1=[1]} [1]

computeIfPresent

default V computeIfPresent(K key, BiFunction remappingFunction)
If the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value.

If the function returns null, the mapping is removed. If the function itself throws an (unchecked) exception, the exception is rethrown, and the current mapping is left unchanged.

官方文档的解释:key存在并且不为空,计算remappingFunction的值value;

如果value不为空,保存指定key和value的映射关系;
如果value为null,remove(key);
如果计算value的过程抛出了异常,computeIfPresent方法中会再次抛出,key和其对应的值不会改变

     Map> map = new HashMap<>();
        map.put(2, Lists.newArrayList(22));
        List xx = map.computeIfPresent(2, (k, v) -> {
            v.add(222);
            return v;
        });
        System.out.println(map + " " + xx);//返回:{2=[22, 222]} [22, 222] 当key存在,插入新value并返回

        xx = map.computeIfPresent(2, (k, v) -> {
            return null;
        });
        System.out.println(map + " " + xx);//返回:{} null 当key存在,插入value=null,remove key并返回null

        map.clear();
        xx = map.computeIfPresent(2, (k, v) -> {
            v.add(222);
            return v;
        });
        System.out.println(map + " " + xx);//返回:{} null 当key不存在,不插入新value,返回null

compute

V oldValue = map.get(key);
 V newValue = remappingFunction.apply(key, oldValue);
 if (oldValue != null ) {
    if (newValue != null)
       map.put(key, newValue);
    else
       map.remove(key);
 } else {
    if (newValue != null)
       map.put(key, newValue);
    else
       return null;
 }

和这段代码意思一样。

官方文档:如果lambda表达式的值不为空,不论key是否已经存在,建立一种映射关系key=newValue;否则,不建立映射并返回null。

     Map> map = new HashMap<>();
        map.put(2, Lists.newArrayList(22));
        List xx = map.compute(2, (k, v) -> {
           return Lists.newArrayList(22, 222);
        });
        System.out.println(map + " " + xx);//返回:{2=[22, 222]} [22, 222] key存在,插入新value并返回

        xx = map.compute(2, (k, v) -> {
            return null;
        });
        System.out.println(map + " " + xx);//返回:{} null 表达式返回null,remove key并返回null

        xx = map.compute(2, (k, v) -> {
            return Lists.newArrayList(22, 222);
        });
        System.out.println(map + " " + xx);//返回:{2=[22, 222]} [22, 222] key不存在,插入新value并返回

小结

putIfAbsent和computeIfAbsent

都是在key不存在的时候才会建立key和value的映射关系;
putIfAbset不论传入的value是否为空,都会建立映射(并不适合所有子类,例如HashTable),而computeIfAbsent方法,当存入value为空时,不做任何操作
当key不存在时,返回的都是新的value(为什么不说新插入的value),即使computeIfAbsent在传入的value为null时,不会新建映射关系,但返回的也是null;


computeIfPresent和computeIfAbsent

这两个方法正好相反,前者是在key存在时,才会用新的value替换oldValue
当传入的key存在,并且传入的value为null时,前者会remove(key),把传入的key对应的映射关系移除;而后者不论何时都不会remove();
前者只有在key存在,并且传入的value不为空的时候,返回值是value,其他情况都是返回null;后者只有在key不存在,并且传入的value不为null的时候才会返回value,其他情况都返回null;


compute
新传入的value不为null就建立映射关系(也就是说不论key是否为null,具体子类再具体分析)
新传入的value为null时:key已存在,且老的对应value不为null,移除改映射关系,返回null;否则,直接返回null

Predicate

Predicate

Predicate是个断言式接口其参数是,也就是给一个参数T,返回boolean类型的结果。Predicate的具体实现也是根据传入的lambda表达式来决定的。

基本示例:

Predicate aa= xx-> xx== 2;
aa.test(xx);

Predicate默认实现的三个重要方法and,or和negate。这三个方法对应了java的三个连接符号&&、|| 和 !。

举例:

        int[] numbers= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
        List list=new ArrayList<>();
        for(int i:numbers) {
            list.add(i);
        }
        Predicate p1=i->i>5;
        Predicate p2=i->i<20;
        Predicate p3=i->i%2==0;
        List test=list.stream().filter(p1.and(p2).and(p3)).collect(Collectors.toList());
        System.out.println(test.toString());
        /** print:[6, 8, 10, 12, 14]*/
List test=list.stream().filter(p1.and(p2).and(p3.negate())).collect(Collectors.toList());
/** print:[7, 9, 11, 13, 15]*/

isEqual这个方法的返回类型也是Predicate,所以我们也可以把它作为函数式接口进行使用。我们可以当做==操作符来使用。

List test=list.stream()
            .filter(p1.and(p2).and(p3.negate()).and(Predicate.isEqual(7)))
            .collect(Collectors.toList());
/** print:[7] */

BiPredicate

相比Predicate,其实就是由1个入参变为2个。

BiPredicate xx = (type, subType) -> type == 20 && (subType == 15);

 

你可能感兴趣的:(Java8常用示例)