Java8 HashMap 的那些高级操作

白发空垂三千丈,一笑人间万事。

1 前言

在日常的开发过程中,经常会使用到 java 的集合框架,特别是在 java8 引入 lambda 表达式后,listmap 的那些操作可谓是出神入化。在本文中将结合自己的开发实践和经验,讲解一下有关 HashMap 相关的高级操作。

2 链式调用

对于 HashMap 使用,大家都不会觉得陌生,它是一个 key-value 的数据结构,通常使用 getput 方法进行数据的获取和存储。通常情况下的业务场景都是使用 list 集合数据转换成 map 进行操作,通过是使用 Collectors.toMap 或者 Collectors.groupingBy 两种方式来转换成 map 数据进行后续数据处理,如下所示:

但是这些都是非常普通的操作,这里使用的是 parallelStream (parallelStream并行处理会比串行处理的Stream要快很多)。

通常情况下,还需要进行数据的过滤,寻找合适的数据再进行处理,这个理念即流式编程。这里使用的是 mapreduce 的操作来处理数据,最终使用累加得到总和。这里采用了两种方式,一种是 mapreduce 的方式,另外一种是 Collectors.reducing 的方式。

less 复制代码
// 使用 mapreduce 方式进行金额累计计算求和
BigDecimal reduce1 = dtoList.stream().filter(node -> NumberUtil.isGreater(node.getAmount(), BigDecimal.ONE))
        .map(OrderInfoDto::getAmount).reduce(BigDecimal.ZERO, NumberUtil::add);
System.out.println("reduce1 " + reduce1);
// 使用 collect 的方式来进行分组计算
BigDecimal reduce2 = dtoList.stream().filter(node -> NumberUtil.isGreater(node.getAmount(), BigDecimal.ONE))
        .collect(Collectors.reducing(BigDecimal.ZERO, OrderInfoDto::getAmount, NumberUtil::add));
System.out.println("reduce2 " + reduce2);

以上介绍的是针对所有的数据进行数据计算,但是在某些特殊业务场景下,需要的操作是需要对数据分组并进行累计计算,这里使用的是 Collectors.groupingByCollectors.reducing 的联合操作,即可实现根据用户 id 分组进行累计求和操作。

less 复制代码
Map<String, BigDecimal> collect = dtoList.stream().filter(node -> NumberUtil.isGreater(node.getAmount(), BigDecimal.ONE))
        .collect(Collectors.groupingBy(OrderInfoDto::getUserId, Collectors.reducing(BigDecimal.ZERO, OrderInfoDto::getAmount, NumberUtil::add)));

3 HashMap 的操作

以上是实现了 mapreduce 的操作好像和 hashmap 没有多大关系,以上的操作是为了理解分组和数据处理,我们将从 compute 实现以上功能的方式来介绍 hashmap 的高级操作。

perl 复制代码
# compute 操作
需要传入的值是一个 key 和 BiFunction, 可以实现新旧数据的处理,这里将两者进行累加并返回。
# computeIfAbsent 如果数据不存在则操作
传入的值是一个 key 和 Function, 可以实现数据的加入,如果数据不存在则加入,存在则不处理
# computeIfPresent 如果数据存在则操作
传入的值是一个 key 和 BiFunction, 如果之前 map 中不存在改值,则不会处理,存在则进行处理。

以上是关于 compute 的操作,在此基础上可以介绍其他的操作。

  • putIfAbsent putIfAbsent 操作是指如果 key 不存在则进行操作,如果 key 存在则不会做任何处理。

  • merge merge 操作时为了实现数据的合并,如果数据不存在则加入,存在则进行合并操作,需要传入 key, value 以及一个 BiFunction, 其入参是对应的值。

  • replace replace 顾名思义是为了替换其值,如果数据存在则替换,不存在则不做任何操作。这里进行替换时,有两种情况,一种是直接替换,另外一种则需要比较其旧值是否一致,一致则修改,不一致则不替换。

  • getOrDefault getOrDefault 是java8 中 map 新增的一个方法,是在根据 key 获取 value 时获取值为 null 时,返回一个默认值,避免空指针的问题发生。

ini 复制代码
// 获取一个返回值,如果 key 不存在则返回一个默认值替代结果。
BigDecimal orDefault = result.getOrDefault("123", BigDecimal.ZERO);
  • 数据去重 这个操作和 hashmap 关系不大,主要是在处理集合数据时,对含有唯一约束的数据进行去重操作。
less 复制代码
List<OrderInfoDto> filterList = dtoList.stream().
        collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(OrderInfoDto::getOrderNo))), ArrayList::new));

4 总结

在本文中,主要介绍了 java8 的链式调用,并在此基础上使用 hashmapcompute 来实现 mapreduce 的操作,从逻辑上理解和实现了相关的操作,然后引出了与 hashmap 相关的其他高级操作,有了这些语法糖,可以很方便的实现业务逻辑,相比 java7 来说进步很大,操作简便,后续会继续分享与编程相关的小技巧和实践经验。本文中所涉及的代码已经上传至 github, 欢迎交流学习。项目地址 springboot-auth

相关推荐
qq_297574672 小时前
【实战】POI 实现 Excel 多级表头导出(含合并单元格完整方案)
java·spring boot·后端·excel
星辰_mya2 小时前
Elasticsearch线上问题之慢查询
java·开发语言·jvm
南极星10052 小时前
我的创作纪念日--128天
java·python·opencv·职场和发展
郝学胜-神的一滴3 小时前
超越Spring的Summer(一): PackageScanner 类实现原理详解
java·服务器·开发语言·后端·spring·软件构建
摇滚侠3 小时前
Java,举例说明,函数式接口,函数式接口实现类,通过匿名内部类实现函数式接口,通过 Lambda 表达式实现函数式接口,演变的过程
java·开发语言·python
Tony Bai3 小时前
“Go 2,请不要发生!”:如果 Go 变成了“缝合怪”,你还会爱它吗?
开发语言·后端·golang
打工的小王3 小时前
java并发编程(七)ReentrantReadWriteLock
java·开发语言
lang201509283 小时前
Java并发革命:JSR-133深度解析
java·开发语言
abluckyboy3 小时前
基于 Java Socket 实现多人聊天室系统(附完整源码)
java·开发语言
Re.不晚3 小时前
JAVA进阶之路——数据结构之线性表(顺序表、链表)
java·数据结构·链表