Collectors.toMap使用详解

news2024/12/25 9:31:11

这里写目录标题

  • 一、使用规则
  • 二、源码及方法
  • 三、代码示例
    • 1.将list转成以id为key的map,value是id对应的Dept对象
    • 2.假如id存在重复值,则会报错Duplicate key xxx, 解决方案是
    • 3.想获得一个id和name对应的Map<Integer, String>
    • 4.把Dept集合按照group分组到map中
    • 5.过滤去重,两个List<Dept>
  • 四、总结

一、使用规则

在实际项目中我们经常会有 List 转 Map 操作,在过去(JAVA8以前)我们可能使用的是 for 循环遍历的方式,这种方式就不做过多赘述。这里主要讲解使用 Collectors.toMap 方式及使用过程需注意的地方,避免踩坑

二、源码及方法

三个重载的方法如下:

//方法一:2个参数
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper) {
    return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
//方法二:3个参数
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper,
                                BinaryOperator<U> mergeFunction) {
    return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}
//方法三:4个参数
public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
                            Function<? super T, ? extends U> valueMapper,
                            BinaryOperator<U> mergeFunction,
                            Supplier<M> mapSupplier) {
    BiConsumer<M, T> accumulator
            = (map, element) -> map.merge(keyMapper.apply(element),
                                          valueMapper.apply(element), mergeFunction);
    return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}

参数含义分别是:

  • keyMapper:Key 的映射函数。
  • valueMapper:Value 的映射函数。
  • mergeFunction:当 Key 冲突时,调用的合并方法。
  • mapSupplier:Map 构造器,在需要返回特定的 Map 时使用。

三、代码示例

首先我们建一个Dept类,属性分别有id,name,group,然后构造一个list:

public class ListToMapDemo {
    public static void main(String[] args) {
        List<Dept> list = new ArrayList<>();
        list.add(new Dept(1,"部门一","1"));
        list.add(new Dept(2,"部门二","2"));
        list.add(new Dept(3,"部门三","3"));
        list.add(new Dept(4,"部门四","4"));
        
    }

    static class Dept{
        private Integer id;
        private String name;
        private String group;

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getGroup() {
            return group;
        }

        public void setGroup(String group) {
            this.group = group;
        }

        public Dept(Integer id, String name, String group) {
            this.id = id;
            this.name = name;
            this.group = group;
        }
 @Override
        public String toString() {
            return "Dept{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", group='" + group + '\'' +
                    '}';
        }
    }
}

1.将list转成以id为key的map,value是id对应的Dept对象

Map<Integer, Dept> map = list.stream().collect(Collectors.toMap(Dept::getId, Function.identity()));
System.out.println(map);
  
 运行结果如下:
 {1=Dept{id=1, name='部门一', group='1'}, 2=Dept{id=2, name='部门二', group='2'}, 
 3=Dept{id=3, name='部门三', group='3'}, 4=Dept{id=4, name='部门四', group='4'}}      

2.假如id存在重复值,则会报错Duplicate key xxx, 解决方案是

只取后一个key及value:

List<Dept> list = new ArrayList<>();
list.add(new Dept(1,"部门一","1"));
list.add(new Dept(2,"部门二","2"));
list.add(new Dept(3,"部门三","3"));
list.add(new Dept(3,"部门四","4"));
Map<Integer, Dept> map = list.stream().collect(Collectors.toMap(Dept::getId, Function.identity(),(oldValue, newValue) -> newValue));
System.out.println(map);

运行结果如下:
{1=Dept{id=1, name='部门一', group='1'}, 2=Dept{id=2, name='部门二', group='2'}, 3=Dept{id=3, name='部门四', group='4'}}

只取前一个key及value:

 Map<Integer, Dept> map = list.stream().collect(Collectors.toMap(Dept::getId,Function.identity(),(oldValue,newValue) -> oldValue));
System.out.println(map);

运行结果如下:
{1=Dept{id=1, name='部门一', group='1'}, 2=Dept{id=2, name='部门二', group='2'},
 3=Dept{id=3, name='部门三', group='3'}}

3.想获得一个id和name对应的Map<Integer, String>

  Map<Integer, String> map = list.stream().collect(Collectors.toMap(Dept::getId,Dept::getName));
  System.out.println(map);
运行结果如下:

{1=部门一, 2=部门二, 3=部门三, 4=部门四}

注意:name可以为空字符串但不能为null,否则会报空指针,解决方案:

Map<Integer, String> map = list.stream().collect(Collectors.toMap(Dept::getId, e -> e.getName() == null ? "" : e.getName()));

假如存在id重复,两个vaue可以这样映射到同一个id:

    Map<Integer, String> map = list.stream().collect(Collectors.toMap(Dept::getId,Dept::getName,(e1, e2)->e1+","+e2));
System.out.println(map);

运行结果如下:
{1=部门一, 2=部门二, 3=部门三,部门四}

4.把Dept集合按照group分组到map中

  Map<String, List<Dept>> map = list.stream().collect(Collectors.groupingBy(Dept::getGroup));
System.out.println(map);


运行结果如下:
{1=[Dept{id=1, name='部门一', group='1'}], 2=[Dept{id=2, name='部门二', group='2'}], 
3=[Dept{id=3, name='部门三', group='3'}, Dept{id=3, name='部门四', group='3'}]}

5.过滤去重,两个List

Map<String, Dept> map2 = list2.stream().collect(Collectors.toMap(Dept::getId,Function.identity()));

//把List1和List2中id重复的Dept对象的name取出来:

List strings = list1.stream().map(Dept::getId).filter(map2::containsKey).map(map2::get).map(Dept::getName).collect(Collectors.toList());

System.out.println(strings);// 输出 [部门2, 部门3]

四、总结

Collectors.toMap 确实带来方便,但是,与此同时,也需要注意两点(你也可以认为是2个坑):

需考虑是否有key重复情况;
需考虑是否有value为null情况。
以上两点在阿里的Java开发手册中也明确指出:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/684418.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5年软件测试工作经验,高不成低不就,真的只能转行了吗?

迷茫感&#xff0c;从哪里来&#xff1f; 不知不觉在软件测试行业&#xff0c;野蛮生长了5年之久。这一路上拥有了非常多的感受。有迷茫&#xff0c;有踩过坑&#xff0c;有付出有收获&#xff0c; 有坚持&#xff01; 我一直都在软件测试行业奋战&#xff0c; 毕业时一起入职…

制作自定义pfx证书(数字签名)

目录 生成server.key 生成server.crt 生成server.pfx 结果 exe文件签名 生成server.key openssl genrsa -des3 -out server.key 2048 Generating RSA private key, 2048 bit long modulus (2 p

单独生成 main.exe, pyinstaller × pyecharts 打包报错找不到文件 map_filename.json 一次搞定!

报错&#xff1a; FileNotFoundError: [Errno 2] No such file or directory: ‘C:\Users\xxx\AppData\Local\Temp_MEI3455\pyecharts\datasets\map_filename.json’ pyecharts 打包成 exe 的时候找不到 map_filename.json 文件。先找到这个文件,一般在本机 Python 安装目录下…

一文掌握linux系统管理命令

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

SuperMap GIS基础产品移动GIS FAQ集锦(3)

SuperMap GIS基础产品移动GIS FAQ集锦&#xff08;3&#xff09; 【iMobile】网络分析中设置权值字段&#xff0c;如何添加多个权值字段&#xff1f; 【解决办法】通过权值字段集合类&#xff08;WeightFieldInfos&#xff09;设置&#xff0c;该类是权值字段信息对象&#x…

回波3DFFT处理(测距、测速、测角)

回波3DFFT处理&#xff08;测距、测速、测角&#xff09; 1、测距、测速2、测角3、3DFFT处理4、MATLAB程序 本文主要针对TI 毫米波雷达的测距、测速、测角的基本方法——3DFFT处理进行简单介绍&#xff0c;并提供MATLAB处理程序&#xff0c;分析3DFFT处理结果。 1、测距、测速…

高等数学下拾遗+与matlab结合

如何学好高等数学 高等数学是数学的一门重要分支&#xff0c;包括微积分、线性代数、常微分方程等内容&#xff0c;它是许多理工科专业的基础课程。以下是一些学好高等数学的建议&#xff1a; 扎实的基础知识&#xff1a;高等数学的内容很多&#xff0c;包括初等数学的一些基…

Postgresql源码(107)analyze行采样流程分析(pg_class中reltuples行数评估是哪里来的准确吗)

总结 pg_class中reltuples行数评估是哪里来的&#xff1f; 行数评估发生在acquire_sample_rows采样函数中&#xff0c;算作采样的副产品之一。 总行数评估totalrows即&#xff1a;扫到页面中live元组的数量 / 扫到多少页面 * 总页面&#xff0c;向上取整。 pg_class中reltu…

十九、socket套接字编程——udp

文章目录 一、socket套接字编程接口&#xff08;一&#xff09;socket头文件&#xff08;二&#xff09;socket 常见API&#xff08;套接字编程接口&#xff09;1. 创建 socket 文件描述符 (TCP/UDP, 客户端 服务器 )2.绑定网络信息 (TCP/UDP, 服务器 )3.开始监听 socket (TCP…

【安装教程】KingFunsion3.6-Windows版本的安装教程

哈喽&#xff01;大家好&#xff0c;我是雷工&#xff01; 由于项目需要今天学习认识KingFunsion3.6及记录Windows版本的安装教程。 一、KingFunsion介绍 1、KingFunsion是什么&#xff1f; KingFunsion是一款面向工程师的管控一体化全组态平台&#xff0c;是一套面向制造企…

Flutter进阶-Future、FutureBuilder、StreamBuilder详解

一、时间循环 Event Loop机制 程序之所以卡说白了就是没有时间更新UI界面刷新屏幕导致 常见的卡顿主要是两种&#xff1a; 1.很大的计算量CPU忙不过来 2.等待&#xff0c;等服务器的响应、等用户的输入、等文件的读取...等等 在多线程的机制里每当遇到需要等的东西就开启一…

管理类联考——逻辑——知识篇——分析推理——二、匹配——haimian

匹配 题型识别 题干一般提供3-5个对象和2~3个维度的信息&#xff0c;并描述某对象及信息间的条件关系&#xff0c;要求将信息进行匹配。要从一个一个条件出发&#xff0c;通过逻辑推理&#xff0c;得出正确答案。 思维导图 解题技巧 注意选项的模式&#xff0c;如果已经将关…

Unity | HDRP高清渲染管线学习笔记:HDRP光照系统(二)

目录 一、光源类型和模式 1. Light组件 1.1 General&#xff08;通用设置&#xff09; 1.1.1 LightLayer&#xff08;光照层&#xff09; 1.2 Emission&#xff08;发光设置&#xff09; 1.3 Shadows&#xff08;阴影&#xff09; 二、Light Layer&#xff08;光源分层&…

【C/C++实战项目】扫雷游戏

目录 项目分析 外部头文件 初始化 打印 扫雷游戏函数 main函数 项目分析 游戏需要自定义地图的大小、埋雷的数量通过输入坐标进行扫雷&#xff0c;输入的坐标是埋雷的地方&#xff0c;则游戏失败输入的坐标未埋雷&#xff0c;则该坐标显示周围8个坐标总共的雷数游戏初始…

Ant Design Vue实现表格双击编辑、添加新行、文字提示

早上刚上班&#xff0c;产品就朝我工位走了过来&#xff0c;一看大事不好&#xff0c;肯定又是来提需求的&#xff01; 产品&#xff1a;做一个表格&#xff0c;要实现双击编辑的功能 我&#xff1a;做不了 产品&#xff1a;老板提的 我&#xff1a;好的&#xff0c;可以做 老板…

什么是测试开发工程师?

目录 前言&#xff1a; SDET是做啥的&#xff1f; 为什么需要测试开发&#xff1f; SDET的角色和职责 技术和软技能 非技术能力&#xff1a; 沟通能力 时间管理和组织能力 良好的工作态度 热情 日常工作 事业进阶 总结 前言&#xff1a; 测试开发工程师 (Software …

AIDL中 Binder 的具体流转过程(源码讲解)

前言 本篇文章承接上篇 Binder对象的流转&#xff08;系统服务的调用过程、AIDL的使用过程&#xff09; 上一篇简单笼统地说明了流转的大致方向与手段&#xff0c;此篇文章我们将深入代码层面&#xff0c;看看 Binder 到底是怎么实现的。 一、一个简单的AIDL示例 客户端&…

网关全局过滤器:Java中的强大工具

文章目录 网关过滤器简介网关过滤器的作用过滤器的生命周期实际应用示例权限过滤器解析 总结 网关过滤器简介 网关过滤器是一个位于应用程序和底层服务之间的组件&#xff0c;它截取进出网络请求&#xff0c;并提供对请求和响应进行处理的机制。它可以在请求到达目标服务之前或…

测试老鸟的职业生涯,从初识到功能再到自动化测试,他都经历了啥...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 张工&#xff1a;…

Qt/C++编写onvif工具(搜索/云台/预置位/OSD/录像存储)

一、前言 从最初编写这个工具开始的时间算起来&#xff0c;至少5年多&#xff0c;一直持续完善到今天&#xff0c;这个工具看起来小也不小大也不大&#xff0c;但是也是经历过无数个现场的洗礼&#xff0c;毫不夸张的说&#xff0c;市面上能够遇到的主流的厂商的设备&#xff…