点击上方蓝色“程序猿DD”,选择“设为星标”

回复“资源”获取独家整理的学习资料!

来源 | juejin.im/post/5d9b455ae51d45782b0c1bfb

Java 8 最大的特性无异于更多地面向函数,比如引入了 lambda等,可以更好地进行函数式编程。前段时间无意间发现了 map.merge() 方法,感觉还是很好用的,此文简单做一些相关介绍。首先我们先看一个例子。

merge() 怎么用?

假设我们有这么一段业务逻辑,我有一个学生成绩对象的列表,对象包含学生姓名、科目、科目分数三个属性,要求求得每个学生的总成绩。加入列表如下:

    private List<StudentScore> buildATestList() {List<StudentScore> studentScoreList = new ArrayList<>();StudentScore studentScore1 = new StudentScore() {{setStuName("张三");setSubject("语文");setScore(70);}};StudentScore studentScore2 = new StudentScore() {{setStuName("张三");setSubject("数学");setScore(80);}};StudentScore studentScore3 = new StudentScore() {{setStuName("张三");setSubject("英语");setScore(65);}};StudentScore studentScore4 = new StudentScore() {{setStuName("李四");setSubject("语文");setScore(68);}};StudentScore studentScore5 = new StudentScore() {{setStuName("李四");setSubject("数学");setScore(70);}};StudentScore studentScore6 = new StudentScore() {{setStuName("李四");setSubject("英语");setScore(90);}};StudentScore studentScore7 = new StudentScore() {{setStuName("王五");setSubject("语文");setScore(80);}};StudentScore studentScore8 = new StudentScore() {{setStuName("王五");setSubject("数学");setScore(85);}};StudentScore studentScore9 = new StudentScore() {{setStuName("王五");setSubject("英语");setScore(70);}};studentScoreList.add(studentScore1);studentScoreList.add(studentScore2);studentScoreList.add(studentScore3);studentScoreList.add(studentScore4);studentScoreList.add(studentScore5);studentScoreList.add(studentScore6);studentScoreList.add(studentScore7);studentScoreList.add(studentScore8);studentScoreList.add(studentScore9);return studentScoreList;}

我们先看一下常规做法:

        ObjectMapper objectMapper = new ObjectMapper();List<StudentScore> studentScoreList = buildATestList();Map<String, Integer> studentScoreMap = new HashMap<>();studentScoreList.forEach(studentScore -> {if (studentScoreMap.containsKey(studentScore.getStuName())) {studentScoreMap.put(studentScore.getStuName(),studentScoreMap.get(studentScore.getStuName()) + studentScore.getScore());} else {studentScoreMap.put(studentScore.getStuName(), studentScore.getScore());}});System.out.println(objectMapper.writeValueAsString(studentScoreMap));// 结果如下:
// {"李四":228,"张三":215,"王五":235}

然后再看一下 merge() 是怎么做的:

        Map<String, Integer> studentScoreMap2 = new HashMap<>();studentScoreList.forEach(studentScore -> studentScoreMap2.merge(studentScore.getStuName(),studentScore.getScore(),Integer::sum));System.out.println(objectMapper.writeValueAsString(studentScoreMap2));// 结果如下:
// {"李四":228,"张三":215,"王五":235}

merge() 简介

merge() 可以这么理解:它将新的值赋值到 key (如果不存在)或更新给定的key 值对应的 value,其源码如下:

    default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {Objects.requireNonNull(remappingFunction);Objects.requireNonNull(value);V oldValue = this.get(key);V newValue = oldValue == null ? value : remappingFunction.apply(oldValue, value);if (newValue == null) {this.remove(key);} else {this.put(key, newValue);}return newValue;}

我们可以看到原理也是很简单的,该方法接收三个参数,一个 key 值,一个 value,一个 remappingFunction ,如果给定的key不存在,它就变成了 put(key, value) 。但是,如果 key 已经存在一些值,我们  remappingFunction 可以选择合并的方式,然后将合并得到的 newValue 赋值给原先的 key。

使用场景

这个使用场景相对来说还是比较多的,比如分组求和这类的操作,虽然 stream 中有相关 groupingBy() 方法,但如果你想在循环中做一些其他操作的时候,merge() 还是一个挺不错的选择的。

其他

除了 merge() 方法之外,我还看到了一些Java 8 中 map 相关的其他方法,比如 putIfAbsent 、compute() 、computeIfAbsent() 、computeIfPresent,这些方法我们看名字应该就知道是什么意思了,故此处就不做过多介绍了,感兴趣的可以简单阅读一下源码(都还是挺易懂的),这里我们贴一下 compute()(Map.class) 的源码,其返回值是计算后得到的新值:

    default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {Objects.requireNonNull(remappingFunction);V oldValue = this.get(key);V newValue = remappingFunction.apply(key, oldValue);if (newValue == null) {if (oldValue == null && !this.containsKey(key)) {return null;} else {this.remove(key);return null;}} else {this.put(key, newValue);return newValue;}}

总结

本文简单介绍了一下 Map.merge() 的方法,除此之外,Java 8 中的 HashMap 实现方法使用了 TreeNode 和 红黑树,在源码阅读上可能有一点难度,不过原理上还是相似的,compute() 同理。所以,源码肯定是要看的,不懂的地方多读多练自然就理解了。

往期推荐

程序员接私活完整攻略+赠开源管理系统

记一次由Redis分布式锁造成的重大事故,避免以后踩坑!

三种 MySQL 大表优化方案

通过这个故事理解啥是 NIO

重磅!GitHub 推出容器镜像仓库服务!

Upwork 发布最赚钱的编程语言 Top 15

我们在星球聊了很多深度话题,你不来看看?

我的星球是否适合你?

点击阅读原文看看我们都聊过啥?

Java 8 中 Map 骚操作之 merge() 的用法相关推荐

  1. java8 stream 分组_Java 8 中 Map 骚操作之 merge() 的用法

    作者:LQ木头来源:http://juejin.im/post/5d9b455ae51d45782b0c1bfb Java 8 最大的特性无异于更多地面向函数,比如引入了 lambda等,可以更好地进 ...

  2. java datediff_JAVA中的时间操作(附DATEDIFF函数用法)

    http://blog.csdn.net/lujiancs/article/details/7043760 //字符串转化成时间类型(字符串可以是任意类型,只要和SimpleDateFormat中的格 ...

  3. Java 8 - Stream流骚操作解读2_归约操作

    文章目录 Pre 什么是归约操作 元素求和 reduce reduce如何运行的 最大值和最小值 Pre Java 8 - Stream流骚操作解读见到过的终端操作都是返回一个 boolean ( a ...

  4. 逆向趣事:那些封印在代码中的骚操作

    在逆向一些正常或恶意软件时,有时会遇到一些作者封印在代码中的骚操作,有趣又另类,甚至可以作为检测规则来应用,今天就来聊聊这些骚操作. 01 - 闲趣型 2012年的时候,Fireye捕获到一个Java ...

  5. JavaScript中的骚操作

    JavaScript中的骚操作--记录自用 JavaScript中的骚操作 数组去重 数组转化为对象(Array to Object) 活用三元表达式 转换为数字类型(Convert to Numbe ...

  6. python中all函数的用法_python中map、any、all函数用法分析

    这篇文章主要介绍了 python 中 map . any . all 函数用法 , 实例分析了 map . any . all 函数 的相关使用技巧 , 具有一定参考借鉴价值 , 需要的朋友可以参考下 ...

  7. Java类中this关键字和static关键字的用法详解

    今天给大家总结介绍一下Java类中this关键字和static关键字的用法. 文章目录 this关键字用法: 1:修饰属性,表示调用类中的成员变量 2:this修饰方法 3:this表示当前对象的引用 ...

  8. java putifabsent_java8中Map的一些骚操作总结

    一 前言 本篇内容是关于 map 新特性的一些方法使用上的介绍,如果有不足之处欢迎补充!! 二 map新特性 关于以下函数式编程的函数的计算知识追寻者都使用 简单字符串代替了,参数无非就是Key,va ...

  9. java map操作_Java 8 中的 Map 骚操作,学习下!

    怎么用? 简介 使用场景 其他 总结 Java 8最大的特性无异于更多地面向函数,有时约会了等,可以更好地进行函数式编程. 前段时间无意间发现了方法,感觉还是很好用的,此文简单做一些相关介绍.首先我们 ...

最新文章

  1. elasticsearch和hadoop集成,gateway.type hdfs设置
  2. 模态对话框和非模态对话框的消息循环
  3. 程序员面试题准备(1)单链表逆置
  4. Ie html button消失,input 按钮在IE下显现不一致的兼容问题
  5. AndroidService 深度分析(2)
  6. Timus 1015. Test the Difference!
  7. linux如何查看vlan信息,dhcp – 通过tcpdump在数据包捕获(Linux)中未显示VLAN标记
  8. 全国草地资源类型分布数据/植被类型分布数据/土地利用类型分布数据
  9. Metronome节拍器
  10. mysql升级_MySQL数据库怎么升级 MySQL数据库升级教程
  11. python合并工作簿所有内容_如何快速的合并多个 Excel 工作簿成为一个工作簿?...
  12. html基础教学ppt,HTML5基础培训ppt课件
  13. Zhishi.me - Weaving Chinese Linking Open Data
  14. Android手机清除锁屏密码
  15. python如何控制鼠标键盘_Python如何控制鼠标键盘
  16. sql语句插入一条记录同时获取刚插入的id
  17. 计算机专业的职业探索,职业教育计算机教学的探索
  18. matlab dat文件乱码,求助MATLAB读取dat数据问题
  19. html5中怎么实现居中显示图片
  20. C++学生选修课程系统设计

热门文章

  1. linux c 获取进程 cpu占用率 内存占用情况
  2. 代码审查工具 sonarqube 简介
  3. python3 中递归的最大次数
  4. linux rpm包解压到当前目录
  5. golang []byte 和 int 互转
  6. 如何用#define宏定义多行函数
  7. windows批处理的感叹号和变量延迟扩展
  8. WIn32中CInternetSession运行异常(afxCurrentAppName 为空)
  9. Pci设备驱动:设备枚举
  10. Linux系统的启动引导过程