基于Map的computeIfAbsent的使用场景和使用方式

目录
  • Map的computeIfAbsent使用场景和方法
    • 常规实现
    • 使用computeIfAbsent方法实现
  • Map中computeIfAbsent() 的作用和底层实现
    • 一、computeIfAbsent() 的作用
    • 二、computeIfAbsent() 的源码实现

Map的computeIfAbsent使用场景和方法

default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
    ...
}

我们在复杂map操作(put操作)时候有的时候不知道此时当前key对应的value值是否存在,这里,我们如果使用常规的代码编写,代码量比较大

例如我们定义一个场景:存在一个数组,我们需要将当前数组中相同的数存储到一个对应List集合中

常规实现

    @Test
    public void test02() {
        //复杂map的使用场景:首先我们说复杂map,即map的value值为一个list集合或者是一个Set集合,对象或者是其他的集合
        //给定一个场景:现在存在一个数组,我们需要将当前数组中相同的数存储到一个对应List集合中
        int[] nums = {1,2,3,1,3,4,6,7,9,9,1,3,4,5};
        Map<Integer, List<Integer>> map = new HashMap<>();
        //普通的写法
        for (int i = 0; i < nums.length; i++) {
            if (!map.containsKey(nums[i])) {
                ArrayList<Integer> list = new ArrayList<>();
                list.add(nums[i]);
                map.put(nums[i],list);
            }else {
                map.get(nums[i]).add(nums[i]);
            }
        }
        map.forEach((key,value) -> {
            System.out.print(key + ": ");
            System.out.println(value);
        });
    }

使用computeIfAbsent方法实现

    @Test
    public void  test03() {
        int[] nums = {1,2,3,1,3,4,6,7,9,9,1,3,4,5};
        Map<Integer, List<Integer>> map = new HashMap<>();
        //我们使用map的computeIfAbsent解决
        for (int i = 0; i < nums.length; i++) {
            //返回值是该key对应的集合list
            map.computeIfAbsent(nums[i], key -> new ArrayList<Integer>());
            map.get(nums[i]).add(nums[i]);
        }

        map.forEach((key,value) -> {
            System.out.print(key + ": ");
            System.out.println(value);
        });
    }

输出结果:

1: [1, 1, 1]
2: [2]
3: [3, 3, 3]
4: [4, 4]
5: [5]
6: [6]
7: [7]
9: [9, 9]

Map中computeIfAbsent() 的作用和底层实现

一、computeIfAbsent() 的作用

最近在开发中,发现同事经常使用Map的computeIfAbsent()方法进行编程,于是对他的实现和作用产生了小兴趣,下面用两个demo案例来简单介绍一下它的作用,然后再对底层实现进行进一步阅读。

作用:判断一个map中是否存在这个key,如果存在则处理value的数据,如果不存在,则创建一个满足value要求的数据结构放到value中。

public class TestComputeIfAbsent {
  static HashMap<String, Set<String>> hashMap = new HashMap<>();
  public static void main(String[] args) {
    Set<String> set = new HashSet<>();
    set.add("zhangSan");
    hashMap.put("china", set);
    // 判断map中是否存在,如果存在则添加元素到set中,如果不存在则新建set添加到hashMap中
    if(hashMap.containsKey("china")) {
      hashMap.get("china").add("liSi");
    } else {
      Set<String> setTmp = new HashSet<>();
      setTmp.add("liSi");
      hashMap.put("china", setTmp);
    }
    System.out.println(hashMap.toString());
  }

在使用了Map的computeIfAbsent() 方法后,使用后以上代码变成了下面的形式(便捷、高效、代码更加优美,但可阅读性降低):

public class TestComputeIfAbsent {
  static HashMap<String, Set<String>> hashMap = new HashMap<>();
  public static void main(String[] args) {
    Set<String> set = new HashSet<>();
    set.add("zhangSan");
    hashMap.put("china", set);
    // after JDK1.8
    hashMap.computeIfAbsent("china", key -> getValues(key)).add("liSi");
    System.out.println(hashMap.toString());
  }

  public static HashSet getValues(String key) {
    return new HashSet();
  }
}

hashMap.computeIfAbsent(“china”, key -> getValues(key)).add(“liSi”);的意思表示key为“China”的建值对是否存在,返回的是value的值。

如果存在则获取china的值,并操作值的set添加数据“lisi"。

如果不存在,则调用方法,新创建set结构,将"lisi"添加到set中,再存入到hashMap中。

二、computeIfAbsent() 的源码实现

这个方法是JDK8中Map类新增的一个方法,用来实现当一个KEY的值缺失的时候,使用给定的映射函数重新计算填充KEY的值并返回结果。computeIfAbsent 方法的JDK源码如下:

default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
	Objects.requireNonNull(mappingFunction);
	V v;
	// 尝试获取KEY的值,如果获取不到KEY
	if ((v = get(key)) == null) {
	    V newValue;
	    // 利用传入的计算函数,得到新的值
	    if ((newValue = mappingFunction.apply(key)) != null) {
	        // 将KEY的值填充为函数计算的结果
	        put(key, newValue);
	        // 返回计算的结果
	        return newValue;
	    }
	}
	// 如果KEY的值存在,则直接返回
	return v;
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • JDK1.8中ConcurrentHashMap中computeIfAbsent死循环bug问题

    死循环问题的提出:https://bugs.openjdk.java.net/browse/JDK-8062841 map.computeIfAbsent("AaAa",key->map.computeIfAbsent("BBBB",key2->42)); computeIfAbsent在1.8中才有的方法 computeIfAbsent意思是:key不存在时候,调用mappingFunction函数结果作为value值 debug 两个key的hash

  • Java8 Map中新增的方法使用总结

    前言 得益于 Java 8 的 default 方法特性,Java 8 对 Map 增加了不少实用的默认方法,像 getOrDefault, forEach, replace, replaceAll, putIfAbsent, remove(key, value), computeIfPresent, computeIfAbsent, compute 和merge 方法.另外与 Map 相关的 Map.Entry 也新加了多个版本的 comparingByKey 和 comparingByVal

  • Java 8 中 Map 骚操作之 merge() 的使用方法

    Java 8 最大的特性无异于更多地面向函数,比如引入了lambda等,可以更好地进行函数式编程.前段时间无意间发现了map.merge()方法,感觉还是很好用的,此文简单做一些相关介绍.首先我们先看一个例子. merge()怎么用? 假设我们有这么一段业务逻辑,我有一个学生成绩对象的列表,对象包含学生姓名.科目.科目分数三个属性,要求求得每个学生的总成绩.加入列表如下: private List<StudentScore> buildATestList() { List<Student

  • 基于Map的computeIfAbsent的使用场景和使用方式

    目录 Map的computeIfAbsent使用场景和方法 常规实现 使用computeIfAbsent方法实现 Map中computeIfAbsent() 的作用和底层实现 一.computeIfAbsent() 的作用 二.computeIfAbsent() 的源码实现 Map的computeIfAbsent使用场景和方法 default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {

  • Android面向切面基于AOP实现登录拦截的场景示例

    目录 前言 一.了解面向切面AOP 二.集成AOP框架 三.定义注解实现功能 总结 前言 场景如下:用户第一次下载App,点击进入首页列表,点击个人页面,需要校验登录,然后跳转到登录页面,注册/登录完成跳转到个人页面. 非常常见的场景,正常我们开发就只能判断是否已经登录,如果未登录就跳转到登录,然后登录完成之后怎么继续执行?如何封装?有哪些方式?其实很多人并不清楚. 这里做一个系列总结一下,看看公共有多少种方式实现,你们使用的是哪一种方案,或者说你们觉得哪一种方案最好用. 这一次分享的是全网最多

  • 基于spring boot 日志(logback)报错的解决方式

    记录一次报错解决方法: No converter found capable of converting from type [java.lang.String] to type [java.util.Map<java.lang.String, java.lang.String>] org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'logging.le

  • 基于Python使用永中文档转换服务的方式

    目录 1 上传文件再转换 2 复合型接口 3 针对在线文档的转换接口 4 小结 因为工作需要,最近开始学习Python:而项目上用到了永中文档转换服务,就想着要不要拿这个练练手.仰仗于Python的易用性,不一会就完成了.现在总结一下,作为二者的简单学习笔记. 1 上传文件再转换 查看了对应的接口文档后,先来上传一个文件试试: def upload():    url = 'http://172.18.21.87:48080/fcscloud/file/upload'    header = {

  • 基于keras输出中间层结果的2种实现方式

    1.使用函数模型API,新建一个model,将输入和输出定义为原来的model的输入和想要的那一层的输出,然后重新进行predict. #coding=utf-8 import seaborn as sbn import pylab as plt import theano from keras.models import Sequential from keras.layers import Dense,Activation from keras.models import Model mod

  • 基于Python3.7.1无法导入Numpy的解决方式

    开发环境:Pycharm 2018.3 + Anaconda3(5.3.0) + Python 3.7.1 + Numpy 1.15.4 在此环境下,我打算使用numpy模块的zeros方法创建一个空的二维List,却屡屡报错 Traceback (most recent call last): File "D:\Anaconda3\lib\site-packages\numpy\core\__init__.py", line 16, in <module> from .

  • python3.6.5基于kerberos认证的hive和hdfs连接调用方式

    1. Kerberos是一种计算机网络授权协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证.具体请查阅官网 2. 需要安装的包(基于centos) yum install libsasl2-dev yum install gcc-c++ python-devel.x86_64 cyrus-sasl-devel.x86_64 yum install python-devel yum install krb5-devel yum install python-krbV pip insta

  • 基于Java中两种jersey文件上传方式

    本文将带领大家使用基于JAX-RS REST风格的实现Jersey来上传文件到服务器制定的文件夹,如果是图片并读取显示出该图片. 准备工作:准备一个form表单,有两个字段,一个是type="file"和type="text",并且表单需要使用POST方式提交.注意改表单需要使用multipart/form-data.该项目使用netbeans8.0和glassfish4.0开发和运行.并且使用maven管理该工程:需要在您的C盘建立一个文件夹,用来存储上传的文件.

  • mysql分表分库的应用场景和设计方式

    很多朋友在论坛和留言区域问mysql在什么情况下才需要进行分库分表,以及采用何种设计方式才是最优的选择,根据这些问题,小编为大家整理了关于MySQL分库分表的应用场景和最优的设计方式举例. 一. 分表 场景:对于大型的互联网应用来说,数据库单表的记录行数可能达到千万级甚至是亿级,并且数据库面临着极高的并发访问.采用Master-Slave复制模式的MySQL架构, 只能够对数据库的读进行扩展,而对数据库的写入操作还是集中在Master上,并且单个Master挂载的Slave也不可能无限制多,Sl

  • 基于Jenkins+Maven+Gitea+Nexus搭建CICD环境的方式

    目录 普通Jar包的运行方式 搭建Nexus私服环境 下载和安装 安装Maven 登录控制台 Nexus控制台说明 目录说明 Nexus设置成系统服务 搭建Gitea环境 搭建Jenkins环境 项目改造 项目配置本地的私服 修改发布服务器的settings.xml文件 配置自动集成与发布 配置Jenkins的环境变量 安装Jenkins插件 配置发布目标服务器信息 添加项目发布机制 编写发布脚本 编写运行脚本run-goods-service.sh 配置代码提交后动态构建 安装Webhook插

随机推荐