• Java Stream流 List< T >转换Map方法汇总合集(大概是最全吧)


    Java Stream流 List< T >转换Map方法汇总合集(大概是最全吧)

    本文主要介绍 Java 中利用 Stream 流将 List< T > 类型数据转换成 Map 类型的几种方法整合汇总,其中包含了toMap()、groupingBy()、partitioningBy()等方法的使用,建议收藏方便查阅,如果有帮助到您,不要吝啬点赞、收藏!

    tips:本文没有推荐使用三方类库提供的 List 转 Map 工具类方法,因为在博主公司引入三方依赖需要在评审时说出引用原因,哈哈哈(太麻烦),当然有很多好用三方工具类可以直接完成 List 转 Map 的操作,如有需要,后续博主会单独写一篇三方类库的 List 转 Map 工具类方法博文提供给大家。

    💗💗💗您的点赞、收藏、评论是博主输出优质文章的的动力!!!💗💗💗

    以下示例会覆盖工作中绝大部分的使用场景,如有没有覆盖到的场景,后续会基于本文持续更新!!所以大家一定要收藏!点赞!欢迎在评论区与博主沟通交流!!👇🏻 👇🏻 👇🏻

    List< String > -> Map< String,List< String>>

    示例一

    通过Stream流完成转换:

     	@Test
        public void testList1() {
            List<String> list = Arrays.asList("s1:01", "s2:02", "s3:03", "s4:04");
            Pattern DELIMITER = Pattern.compile(":");
            Map<String, List<String>> map = list.stream().map(DELIMITER::split)
                    .collect(Collectors.groupingBy(a -> a[0],
                            Collectors.mapping(a -> a[1], Collectors.toList())));
            System.out.println(JSONObject.toJSONString(map));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果:
    在这里插入图片描述

    示例二

    通过forEach循环转换:

        @Test
        public void testList1() {
            List<String> list = Arrays.asList("s1:01", "s2:02", "s3:03", "s4:04");
            Map<String, Set<String>> map = new HashMap<>();
            list.forEach(location -> {
                String[] strArr = location.split(":");
                map.compute(strArr[0], (country, codes) -> {
                    codes = codes == null ? new HashSet<>() : codes;
                    codes.add(strArr[1]);
                    return codes;
                });
            });
            System.out.println(JSONObject.toJSONString(map));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    运行结果:

    在这里插入图片描述

    List< T > -> Map< T, T >

    List< Integer> -> Map< Integer,Integer>

    代码示例(本示例是存在重复key,并且会以首个出现的 key 去覆盖后面出现的冲突 key):

     	@Test
        public void testList2() {
            List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 4, 5, 6, 7, 8);
            Map<Integer, Integer> collect = list.stream().collect(Collectors.toMap(k -> k, v -> v, (k1, k2) -> k1));
            System.out.println("collect:" + collect);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    toMap()无重复key

    示例一

    List泛型为 Student 对象,示例需要将name属性作为 key,age 属性作为value;

        @Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
            Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
            System.out.println(JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    示例二

    List泛型为 Student 对象,示例需要将name属性作为 key, Student 对象作为value;

    @Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
            Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student));
            System.out.println(JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果:

    在这里插入图片描述

    toMap()有重复key

    当存在重复 key 时,编译器会报错:java.lang.IllegalStateException: Duplicate key xxxx;
    在这里插入图片描述

    出现这种情况就需要在 toMap() 方法中指定 key 来避免冲突;

    示例一

    解决办法:使用第一个key 覆盖第二个key;

        @Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
            Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student, (key1, key2) -> key1));
            System.out.println(JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果(保留了 “num”:11 的对象):

    在这里插入图片描述

    示例二

    解决办法:使用第二个key 覆盖第一个key;

    	@Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
            Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student, (key1, key2) -> key2));
            System.out.println(JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果(保留了 “num”:2 的对象):

    在这里插入图片描述

    toMap()空指针异常

    当 value 为空时,使用 toMap() 方法进行转换,编译器会抛出 java.lang.NullPointerException;

    	@Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
                    new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
            Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
            System.out.println(JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果:

    在这里插入图片描述

    解决办法一

    转换时增加判断,如果是null,则设置默认值;

    	@Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
                    new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
            Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, s -> s.getAge() == null ? -1 : s.getAge()));
            System.out.println(JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果:

    在这里插入图片描述

    解决办法二

    使用 Optional< T > 对值进行包装(和方式一大同小异,就是换了个写法):

    	@Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
                    new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
            Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName,  s -> Optional.ofNullable(s.getAge()).orElse(-1)));
            System.out.println("Optional:"+JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果:

    在这里插入图片描述

    解决办法三

    使用collect(Supplier< R > supplier, BiConsumer accumulator, BiConsumer combiner) 来构建,可允许null值的出现:

    	@Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
                    new Student(null, 12, DateUtil.parse("2007-02-21 22:18:56"), null));
            HashMap<Integer, String> collect = list.stream().collect(HashMap::new, (obj, v) -> obj.put(v.getAge(), v.getName()), HashMap::putAll);
            System.out.println("collect:" + collect);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果:

    在这里插入图片描述

    List< T > -> Map< T, List< T > >

    groupingBy()

    直接根据一个字段或者属性分组也可以直接用 groupingBy() 方法:

    	@Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
            Map<String, List<Student>> collect = list.stream().collect(Collectors.groupingBy(Student::getName));
            System.out.println(JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果:

    在这里插入图片描述

    partitioningBy()

    partitioningBy() 可以理解为特殊的 groupingBy() ,key 值为 Boolean类型:

    	@Test
        public void testList2() {
            List<Student> list = Lists.newArrayList(
                    new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                    new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
                    new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
            Map<Boolean, List<Student>> collect = list.stream().collect(Collectors.partitioningBy(s -> s.getNum() >= 5));
            System.out.println(JSONObject.toJSONString(collect));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果:

    在这里插入图片描述


    感 谢 各 位 大 佬 的 阅 读,随 手 点 赞,日 薪 过 万~! !!
  • 相关阅读:
    用预训练好的VGG16网络+ImageNet(用于图像分类的1000个类别标签)对图片类别做出预测
    一篇文章学会React
    MySQL 中分区表
    SpringBoot概述
    RK3399平台开发系列讲解(进程篇)15.36、理解进程和协程
    golang singleflight资料整理
    【论文笔记】A theory of learning from different domains
    算法错题簿(持续更新)
    【老生谈算法】matlab实现线性分组码编译源码——线性分组码编译
    Git教程——git使用
  • 原文地址:https://blog.csdn.net/zhuzicc/article/details/133983596