相关文章推荐
俊秀的灌汤包  ·  怎么在Excel中给不足位数的数字前面补0, ...·  1 年前    · 
仗义的单车  ·  pandas 筛选数据的 8 ...·  1 年前    · 
爱搭讪的消炎药  ·  PowerShell ...·  1 年前    · 
高大的麦片  ·  驱动程序无法通过使用安全套接字层(SSL)加 ...·  1 年前    · 
腹黑的烈酒  ·  Grafana / Server ...·  2 年前    · 
Code  ›  Java8合并两个Map中元素的正确姿势开发者社区
https://cloud.tencent.com/developer/article/1868916
捣蛋的皮带
2 年前
作者头像
明明如月学长
0 篇文章

Java8合并两个Map中元素的正确姿势

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > 明明如月的技术专栏 > Java8合并两个Map中元素的正确姿势

Java8合并两个Map中元素的正确姿势

作者头像
明明如月学长
发布 于 2021-08-27 16:28:22
4.6K 0
发布 于 2021-08-27 16:28:22
举报

英文原文地址: https://www.baeldung.com/java-merge-maps

1. 介绍

本入门教程将介绍Java8中如何合并两个map。

更具体说来,我们将研究不同的合并方案,包括Map含有重复元素的情况。

2. 初始化

我们定义两个map实例

private static Map map1 = new HashMap<>();
private static Map map2 = new HashMap<>();

Employee类

public class Employee {
    private Long id;
    private String name;
    // 此处省略构造方法, getters, setters方法
}

然后往map中存入一些数据

Employee employee1 = new Employee(1L, "Henry");
map1.put(employee1.getName(), employee1);
Employee employee2 = new Employee(22L, "Annie");
map1.put(employee2.getName(), employee2);
Employee employee3 = new Employee(8L, "John");
map1.put(employee3.getName(), employee3);
Employee employee4 = new Employee(2L, "George");
map2.put(employee4.getName(), employee4);
Employee employee5 = new Employee(3L, "Henry");
map2.put(employee5.getName(), employee5);

特别需要注意的是 employee1 和 employee5在map中有完全相同的key(name)。

3. Map.merge()

Java8为 java.util.Map接口新增了merge()函数。

merge() 函数的作用是: 如果给定的key之前没设置value 或者value为null, 则将给定的value关联到这个key上.

否则,通过给定的remaping函数计算的结果来替换其value。如果remapping函数的计算结果为null,将解除此结果。

First, let’s construct a new HashMap by copying all the entries from the map1 :

首先,我们通过拷贝map1中的元素来构造一个新的 HashMap

Map map3 = new HashMap<>(map1);

然后引入merge函数和合并规则

map3.merge(key, value, (v1, v2) -> new Employee(v1.getId(),v2.getName())

最后对map2进行迭代将其元素合并到map3中

map2.forEach(
  (key, value) -> map3.merge(key, value, (v1, v2) -> new Employee(v1.getId(),v2.getName())));

运行程序并打印结果如下:

John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
Henry=Employee{id=1, name='Henry'}

最终,通过结果可以看出,实现了两个map的合并,对重复的key也合并为同一个元素。

注意最后一个 Employee 的id来自map1而name来自map2.

原因是我们的merge函数的定义

(v1, v2) -> new Employee(v1.getId(), v2.getName())

4. Stream.concat()

Java8的Stream API 也为解决该问题提供了较好的解决方案。

首先需要将两个map合为一个 Stream。

Stream combined = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream());

我们需要将entry sets作为参数,然后利用 Collectors.toMap() :将结果放到新的map中。

Map result = combined.collect(
  Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

该方法可以实现map的合并,但是有重复key会报 IllegalStateException异常。

为了解决这个问题,我们需要加入lambda表达式merger作为第三个参数

(value1, value2) -> new Employee(value2.getId(), value1.getName())

当检测到有重复Key时就会用到该lambda表达式。

现在把上面代码组合在一起:

Map result = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream())
  .collect(Collectors.toMap(
    Map.Entry::getKey, 
    Map.Entry::getValue,
    (value1, value2) -> new Employee(value2.getId(), value1.getName())));

最终的结果

George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}
Henry=Employee{id=3, name='Henry'}

从结果可以看出重复的key “Henry”将合并为一个新的键值对,id取自map2,name取自map1。

5. Stream.of()

通过Stream.of()方法不需要借助其他stream就可以实现map的合并。

Map map3 = Stream.of(map1, map2)
  .flatMap(map -> map.entrySet().stream())
  .collect(Collectors.toMap(
    Map.Entry::getKey,
    Map.Entry::getValue,
    (v1, v2) -> new Employee(v1.getId(), v2.getName())));

首先将map1和map2的元素合并为同一个流,然后再转成map。通过使用v1的id和v2的name来解决重复key的问题。

map3的运行打印结果如下:

6. Simple Streaming

我们还可以借助stream的管道操作来实现map合并。

Map map3 = map2.entrySet()
  .stream()
  .collect(Collectors.toMap(
    Map.Entry::getKey,
    Map.Entry::getValue,
    (v1, v2) -> new Employee(v1.getId(), v2.getName()),
  () -> new HashMap<>(map1)));

结果如下:

{John=Employee{id=8, name='John'}, 
Annie=Employee{id=22, name='Annie'}, 
George=Employee{id=2, name='George'}, 
Henry=Employee{id=1, name='Henry'}}

7. StreamEx

我们还可以使 Stream API 的增强库

Map map3 = EntryStream.of(map1)
 
推荐文章
俊秀的灌汤包  ·  怎么在Excel中给不足位数的数字前面补0,方法二你肯定想不到|字符串|代码_网易订阅
1 年前
仗义的单车  ·  pandas 筛选数据的 8 个骚操作-腾讯云开发者社区-腾讯云
1 年前
爱搭讪的消炎药  ·  PowerShell 管道符之Select的使用方法【一】 - PowerShell届的小白白 - 博客园
1 年前
高大的麦片  ·  驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误_“The server selected protocol version TLS10 is not acc
1 年前
腹黑的烈酒  ·  Grafana / Server Error_grafana 只读_赵保军的博客-CSDN博客
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号