详解Java8合并两个Map中元素的正确姿势
1.介绍
本入门教程将介绍Java8中如何合并两个map。
更具体说来,我们将研究不同的合并方案,包括Map含有重复元素的情况。
2.初始化
我们定义两个map实例
privatestaticMapmap1=newHashMap<>(); privatestaticMap map2=newHashMap<>();
Employee类
publicclassEmployee{ privateLongid; privateStringname; //此处省略构造方法,getters,setters方法 }
然后往map中存入一些数据
Employeeemployee1=newEmployee(1L,"Henry"); map1.put(employee1.getName(),employee1); Employeeemployee2=newEmployee(22L,"Annie"); map1.put(employee2.getName(),employee2); Employeeemployee3=newEmployee(8L,"John"); map1.put(employee3.getName(),employee3); Employeeemployee4=newEmployee(2L,"George"); map2.put(employee4.getName(),employee4); Employeeemployee5=newEmployee(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'sconstructanewHashMapbycopyingalltheentriesfromthemap1:
首先,我们通过拷贝map1中的元素来构造一个新的HashMap
Mapmap3=newHashMap<>(map1);
然后引入merge函数和合并规则
map3.merge(key,value,(v1,v2)->newEmployee(v1.getId(),v2.getName())
最后对map2进行迭代将其元素合并到map3中
map2.forEach( (key,value)->map3.merge(key,value,(v1,v2)->newEmployee(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)->newEmployee(v1.getId(),v2.getName())
4.Stream.concat()
Java8的StreamAPI也为解决该问题提供了较好的解决方案。
首先需要将两个map合为一个Stream。
Streamcombined=Stream.concat(map1.entrySet().stream(),map2.entrySet().stream());
我们需要将entrysets作为参数,然后利用Collectors.toMap():将结果放到新的map中。
Mapresult=combined.collect( Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
该方法可以实现map的合并,但是有重复key会报IllegalStateException异常。
为了解决这个问题,我们需要加入lambda表达式merger作为第三个参数
(value1,value2)->newEmployee(value2.getId(),value1.getName())
当检测到有重复Key时就会用到该lambda表达式。
现在把上面代码组合在一起:
Mapresult=Stream.concat(map1.entrySet().stream(),map2.entrySet().stream()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (value1,value2)->newEmployee(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的合并。
Mapmap3=Stream.of(map1,map2) .flatMap(map->map.entrySet().stream()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (v1,v2)->newEmployee(v1.getId(),v2.getName())));
首先将map1和map2的元素合并为同一个流,然后再转成map。通过使用v1的id和v2的name来解决重复key的问题。
map3的运行打印结果如下:
6.SimpleStreaming
我们还可以借助stream的管道操作来实现map合并。
Mapmap3=map2.entrySet() .stream() .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (v1,v2)->newEmployee(v1.getId(),v2.getName()), ()->newHashMap<>(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
我们还可以使StreamAPI的增强库
Mapmap3=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'}}
8总结
本文使用了Map.merge(),StreamAPI,StreamEx库实现map的合并。
英文原文地址:https://www.baeldung.com/java-merge-maps
到此这篇关于详解Java8合并两个Map中元素的正确姿势的文章就介绍到这了,更多相关Java8合并Map中元素内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。