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

相关推荐
苏三说技术28 分钟前
Claude Code从失控到起飞,只用了这些技巧
后端
长栎1 小时前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode1 小时前
Redis 在生产项目的使用
前端·后端
用户559822481222 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端
LiaCode2 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战2 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
xiaodaoluanzha2 小时前
迄今為止,最簡單的編程語言 Nolang
前端·后端
Csvn2 小时前
Docker 容器管理入门 — 从镜像到容器编排
后端
用户762352425912 小时前
ShardingJDBC
后端
行者全栈架构师2 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端