java8的lambda中的map相关操作

技术标签: java8/9/11  lambda  java8  java·未分类  merge  map  

 

0 入门详解篇

 史上最简单入门:java8的lambda中的map相关操作:基础及注意事项图文详解

2   java8的lambda中collect接口案例及原理详解,官方文档解读

3   java8:封装lambda泛型工具类之list转为map

 


1 以下是正文

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

原文链接:https://blog.csdn.net/w605283073/article/details/82987157

1. 介绍

本入门教程将介绍Java8中如何合并两个map。如果想学习入门教程点击开篇0入门篇lambda表达式:list转map

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

2. 初始化

我们定义两个map实例

private static Map<String, Employee> map1 = new HashMap<>();

private static Map<String, Employee> 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<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'}}

8 总结

本文使用了Map.merge(), Stream API, StreamEx 库实现map的合并。

本文源码:https://github.com/eugenp/tutorials/tree/master/core-java-collections

二:Java8使List转为Map

https://blog.csdn.net/hanerer1314/article/details/78826068

import com.yang.test.User;
 
import javax.jws.soap.SOAPBinding;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
 
public class Main {
 
    public static void main(String[] args) {
 
        List<User> userlist = new ArrayList<>();
        for (int i = 0; i <10; i++) {
 
            userlist.add(new User("张三"+i,i));
        }
        System.out.println(getAllages(userlist).size());
 
        System.out.println(getUser2Map(userlist));
 
        System.out.println(getUser2MapUser(userlist));
 
        System.out.println(getUser2MapUser2(userlist));
 
          System.out.println(getUser2MapUser3(userlist));
 
    }
 
    public static List<Integer> getAllages(List<User>userlist){
        return  userlist.stream().map(user -> user.getAge()).collect(Collectors.toList());
    }
 
    public static Map<Integer,String> getUser2Map(List<User>userlist){
 
        return userlist.stream().collect(Collectors.toMap(User::getAge,User::getName));
    }
 
    public static Map<Integer,User> getUser2MapUser(List<User>userlist){
 
        return userlist.stream().collect(Collectors.toMap(User::getAge,User-> User));
    }
 
    /**
     * 比较优雅的写法是这样的
     * @param userlist
     * @return
     */
    public static Map<Integer,User> getUser2MapUser2(List<User>userlist){
 
        return userlist.stream().collect(Collectors.toMap(User::getAge, Function.identity()));
    }
 
    /**
     * 重复key的情况下 简单的使用后者覆盖前者的
     */
    public static Map<Integer,User> getUser2MapUser3(List<User>userlist){
 
        return userlist.stream().collect(Collectors.toMap(User::getAge, Function.identity(),(key1,key2)->key2));
    }
 
    /**
     *指定map的具体实现
     * @param userlist
     * @return
     */
    public static Map<Integer,User> getUser2MapUser4(List<User>userlist){
 
        return userlist.stream().collect(Collectors.toMap(User::getAge, Function.identity(),(key1,key2)->key2, LinkedHashMap::new));
    }
}

Function.identity()用的默认的也可以是x->x 即value是user

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wabiaozia/article/details/84262195

智能推荐

Spring框架(四)SpringMVC基础_恒哥~Bingo的博客-程序员宝宝

目录1、SpringMVC概述1.1 回顾MVC设计模式1.1.1 MVC的概念1.1.2 MVC的执行流程1.2 Struts2.0和SpringMVC的区别1.2.1 MVC框架的演变1.2.2 Struts2.0和SpringMVC的区别2、入门案例3、SpringMVC执行流程4、参数处理4.1 SpringMVC的常用注解4.2 参数绑定5、返回数据5.1 SpringMVC实现返回数据5.2 页面跳转5.3 简单登录案例1、SpringMVC概述SpringMVC是Spring进行Web开发

Condition----await,signal分析_好一个迷途小书童的博客-程序员宝宝

Condition由来 在前面synchronized的时候,有讲到wait/notify的基本使用,结合shnchronized可以实现对线程通信。那么这个时候我就思考了,既然JUC里面提供了锁的实现机制,那么JUC里面有没有提供类似的线程通信的工具呢?于是找啊找,发现了一个condition工具类 Condition是一个多线程协调通信工具类,可以让某些线程一起等待某个条件(con dition),只有满足条件时,线程才会被唤醒, 案例如下:public class Conditio

html调用js函数取随机返回数值并自动显示在html页面_社群讲课大师的博客-程序员宝宝_js取随机数

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

[ASP.NET如何在客户端调用服务端代码_大新软件技术部的博客-程序员宝宝

http://blog.csdn.net/xujh/比如我们在页面上有3个TextBox,3个Button,每个Button分别执行不同的动作。我们现在想在TextBox中检测是否按下了回车键,如果是则执行不同的Button调用。即TextBox1中按下回车就执行Button1的动作,...... 测试中,我发现要调用服务器端代码必须调用__doPostBack函数,但该函数除了在放置有DataG

VBA实现EXCEL转DBC_枯无穷肉的博客-程序员宝宝

利用VBA实现对EXCEL转成DBC文件EXCEL的格式如下:VBA代码:Sub exceltodbc() Dim i, j As Integer Dim row As Integer Dim filepath, GenMsgCycleTime, CM, VAL As String Dim MsgName, MsgId, MsgCyc...

随便推点

黑马程序员————结构体学习笔记_Cherrycool2015的博客-程序员宝宝

-----------android培训、java培训、java学习型技术博客、期待与您交流!------------                                                               结构体1.1、结构体类型介绍        在实际问题中,一组数据不会只有单一的数据类型。比如,公司员工信息,员工姓名为字符型,工号为整型或

creating base64 hashes using HMAC SHA256_weixin_33995481的博客-程序员宝宝

为什么80%的码农都做不了架构师?&gt;&gt;&gt; ...

世界国家经纬度列表_X01动力装甲的博客-程序员宝宝_各国经纬度

这个网站不错,可以直接查询国家的经纬度,输入国家、城市、地区的名字就可以,https://www.latlong.net/英文搜素,也支持中文,不过不太友好。比如我搜素日本,结果定位到香港,搜素Japan的时候才是对的。搜素区域、国家一般会定位到区域的中央位置。...

Python自动化运维学习笔记(三)_X丶zccc的博客-程序员宝宝

IP地址处理模块IPyIPy是一个功能强大的第三方模块,它可以很好的辅助完成IP的规划或计算工作IPy模块安装首先进入虚拟环境,然后使用pip安装IPy模块source bin/activatepip install IPyIP类常见方法在日常使用中,常见的IP操作包括IP类型判断、IP转换、反向解析、输出网段地址等。&amp;amp;gt;&amp;amp;gt;&amp;amp;gt; from IPy import IP...

Docker in Docker_Chai Yingchao的博客-程序员宝宝

场景:jenkins slave运行在基于openshift或k8s的容器中,构建过程需要build 应用程序的docker image并push到docker 仓库,此时就需要docker命令。安装docker命令比较简单,但是运行docker build 命令需要启动docker服务。docker in docker 基本上有两种实现方式。一是挂载/var/run/docker.so...

推荐文章

热门文章

相关标签