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<String, Employee> 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<String, Employee> 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<String, Employee> 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<String, Employee> 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<String, Employee> 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<String, Employee> map3 = EntryStream.of(map1)
.append(EntryStream.of(map2))
.toMap((e1, e2) -> e1);
注意 (e1, e2) -> e1 表达式来处理重复key的问题,如果没有该表达式依然会报IllegalStateException异常。
{George=Employee{id=2, name='George'},
John=Employee{id=8, name='John'},
Annie=Employee{id=22, name='Annie'},
Henry=Employee{id=1, name='Henry'}}
本文使用了Map.merge(), Stream API, StreamEx 库实现map的合并。
本文源码:https://github.com/eugenp/tutorials/tree/master/core-java-collections
欢迎加入我的知识星球,知识星球ID:15165241 一起交流学习。
https://t.zsxq.com/Z3bAiea,申请时标注来自CSDN。
欢迎加入我们的 slack 工作区,在里面可以对ai 和我进行提问。
https://join.slack.com/t/ai-yx51081/shared_invite/zt-1t8cp1lk3-ZMAFutZcN3PCW~8WQDGjPg
在Java 8中,我们可以使用带有lambda表达式的Stream对象的map()方法将对象转换为另一种类型。 map()方法是流对象中的中间操作,因此我们需要一种终端方法来完成流。语法Streammap(FunctionsuperT,?extendsR>mapper)示例importjava.util.*;importjava.util.stream.*;publicc...
Map是一个集合对象,它将键映射到Java中的值。 数据可以存储在键/值对中,并且每个键都是唯一的。 这些键/值对也称为映射条目。在下面的示例中,我们可以使用lambda表达式填充映射。我们已经将字符和可运行参数传递给Map对象,并将lambda表达式作为Map类的put()方法中的第二个参数传递。我们需要传递命令行参数,用户是否在Scanner类的帮助下输入“h”表示帮助,输入“q”表示退出。示...
利用Java将lambda list转换map并实现拼接参数发布时间:2020-11-07 16:44:14来源:亿速云阅读:147作者:Leah本篇文章给大家分享的是有关利用Java将lambda list转换map并实现拼接参数,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。我就废话不多说了,大家还是直接看代码吧~Map parts...
我有一个具有这种结构的Object:@JsonProperty("id")private Long codigoCategoria;@JsonProperty("parentId")private Long codigoCategoriaPai;@JsonProperty("name")private String nomeCategoria;@JsonInclude(JsonInclude.In...
前言本篇主要讲述是Java中JDK1.8的一些新语法特性使用,主要是Lambda、Stream和LocalDate日期的一些使用讲解。LambdaLambda介绍Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda...