JDK8中Map新增方法的使用(comparingByXX方法、putIfAbsent方法、compute相关方法、merge方法等)

前言:

Map是java中常用使用的一个集合类,它以键值对的形式存储数据。我们经常使HashMap、Concurrenthashmap等都是Map接口的实现类。在JDK8中Map集合类进行非常多的优化,比如。HashMap的数据结构从“数组+链表”变成了“数组+链表+红黑树”(PS:我会写一篇HashMap源码的文章);Concurrenthashmap在JDK7版本中使用“分段锁技术”保证线程安全,而JDK8中使用“synchronized+CAS”保证线程安全。此外,在JDK8中Map又新增了11个方法,增加了Map集合类使用的便捷性和灵活。这篇文章,我们将选取几个重要的方法进行使用,希望对大家的工作学习有些帮助。

正文:

一、新增的11个方法:

getOrDefault(Object key, V defaultValue)、forEach(BiConsumer<? super K, ? super V> action)、replaceAll(BiFunction<? super K, ? super V, ? extends V> function) 、putIfAbsent(K key, V value) 、remove(Object key, Object value) 、replace(K key, V oldValue, V newValue)、replace(K key, V value)、computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)、computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)、compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)、merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)

二、重点方法的使用:

我在将用Map接口的实现类HashMap演示重点方法的使用,为了方便阅读和断点运行HashMap源码,我又将源码复制MyHashMap类中,以下事例都是实例化MyHashMap类,它的本质还是HashMap。

1.putIfAbsent(K key, V value):

作用:如果Map不存在这样的映射时,使用putIfAbsent(K key,V value)方法来添加键值对。

特点:key不存在时,添加key-value映射对; key为null时,覆盖value值

举例: 

    Map<String, String> map = new MyHashMap<>();
    map.put("a1", "123");
    map.put("a2", null);
    map.putIfAbsent("a1", "a1");
    map.putIfAbsent("a2", "a2");
    map.putIfAbsent("a3", "a3");
    map.putIfAbsent("a4", null);
    System.out.println("遍历 map:"+map); //遍历 map:{a1=123, a2=a2, a3=a3, a4=null}

2.compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction):

作用:获取指定key,通过BiFunction函数更新过的value值。

特点:如果在compute中传递的重映射函数返回null,则将映射从Map中删除;如果重映射函数引发异常,则异常为re-thrown,并且当前映射保持不变;在计算过程中,重新映射功能应该不能修改此映射。

 举例: 

    Map<String, Integer> map = new MyHashMap<>();
    map.put("aj1", 1000);
    map.put("aj2", null);
    map.put("aj3", 2000);
    // compute简单使用:
    Integer aj1 = map.compute("aj1", (key, value) -> value * 90 / 100);
    System.out.println("aj1打9折: " + aj1); //aj1打9折: 900
    // 证明1:如果在compute中传递的重映射函数返回null,则将映射从Map中删除(存在的key的value可以为空)。
    Integer aj2 = map.compute("aj2", (key, value) -> value == null ? null : value * 90 / 100);
    System.out.println("aj2打9折: " + aj2);  //aj2打9折: null
    // 证明2:如果重映射函数引发异常,则异常为re-thrown,并且当前映射保持不变
    Integer aj3 = null;
    try {
        aj3 = map.compute("aj3", (key, value) -> "aj3".equals(key) ? value / 0 : value * 90 / 100);
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("aj3的值: " + map.get("aj3"));  //aj3的值: 2000
    System.out.println("打印map:" + map);  //打印map:{aj1=900, aj3=2000}

3.computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction):

作用:获取不存在的key或映射值为null的key,通过Function函数更新过的value值。即key不存在时,计算value后,添加key-value映射对;key为null时,计算value后,覆盖value值。

特点:如果此方法的映射函数返回null,则不会为该键记录任何映射;在计算时,如果重新映射函数引发异常,则重新引发该异常,并且不记录任何映射;在计算过程中,不允许使用此方法修改此Map。

 举例:  

    Map<String, Integer> map = new MyHashMap<>();
    map.put("aj1", 1000);
    map.put("aj2", null);
    map.put("aj3", 1200);
    Integer aj1 = map.computeIfAbsent("aj1", key -> 1500+100);
    System.out.println("aj1存在时,返回原value:" + aj1); // aj1存在时,返回原value:1000
    Integer aj2 = map.computeIfAbsent("aj2", key -> 1700);
    System.out.println("aj2为空时,覆盖value值:" + aj2); // aj2为空时,覆盖value值:1700
    Integer aj4 = map.computeIfAbsent("aj4", key -> 2000);
    System.out.println("aj4不存在时,添加value值:" + aj4); // aj4不存在时,添加value值:2000
    System.out.println("打印map:" + map);  //打印map:{aj2=1700, aj1=1000, aj4=2000, aj3=1200}

    // 统计出现数量
    Map<String, AtomicInteger> map1 = new MyHashMap<>();
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("2");
    list.add("4");
    list.add("5");
    list.add("1");
    list.forEach(str -> map1.computeIfAbsent(str, key -> new AtomicInteger()).incrementAndGet());
    System.out.println("打印map1:" + map1);

4.computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction):

作用:获取存在的key或映射值为null的key,通过BiFunction函数更新过的value值

 特点:如果此方法的映射函数返回null,则将删除该映射(前提,存在的key的value不为空);如果重新映射函数引发异常,则重新引发该异常,并且映射保持不变;在计算过程中,不允许使用此方法修改此Map

  举例:  

    Map<String, Integer> map = new MyHashMap<>();
    map.put("aj1", 1000);
    map.put("aj2", null);
    map.put("aj3", 2000);
    Integer aj1 = map.computeIfPresent("aj1", (key, value) -> value == null ? null : value * 90 / 100);
    System.out.println("aj1打9折: " + aj1);  // aj1打9折: 900
    Integer aj2 = map.computeIfPresent("aj2", (key, value) -> value == null ? null : value * 90 / 100);
    System.out.println("aj2打9折: " + aj2);  // aj2打9折: null
    Integer aj4 = map.computeIfPresent("aj4", (key, value) -> value == null ? null : value * 90 / 100);
    System.out.println("aj4打9折: " + aj4);  // aj4打9折: null
    // 证明:如果此方法的映射函数返回null,则将删除该映射(前提,存在的key的value不为空);
    Integer aj3 = map.computeIfPresent("aj3", (key, value) -> value != null ? null : value * 90 / 100);
    System.out.println("aj3打9折: " + aj3); // aj3打9折: null
    System.out.println("打印map:" + map); // 打印map:{aj2=null, aj1=900}

5.merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction):

作用:获取key,通过BiFunction函数计算组合一个键的多个映射值。

 特点:如果键不存在或与null关联,则仅将键以及Hashmap中的相应值作为新条目输出;如果键已经具有某个值,则“重新映射功能”会将旧值和新值都与给定键合并。

  举例:  

    // 仓库1鞋种类及个数
    Map<String, Integer> map1 = new MyHashMap<>();
    map1.put("aj1", 10);
    map1.put("aj2", 3);
    map1.put("aj3", 5);
    // 仓库2鞋种类及个数
    Map<String, Integer> map2 = new MyHashMap<>();
    map2.put("aj2", 8);
    map2.put("aj3", 1);
    map2.put("aj4",10);
    // 使用merge计算合计
    map2.forEach((key, value) ->
        map1.merge(key, value, (v1, v2) -> 
                v1.equals(v2) ? v1 : v1 + v2)
    );
    System.out.println("所有仓库的鞋的种类及个数:" + map1);  // 所有仓库的鞋的种类及个数:{aj2=11, aj1=10, aj4=10, aj3=6}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hanxiaozhang2018

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值