java 8 stream toMap key的重复问题

本文讲述了在Java8中使用Stream将List中Person对象的姓名和年龄映射到Map时遇到的key重复问题,介绍了toMap方法的三个参数及其作用,并提供了冲突解决策略和groupingBy替代方案。
摘要由CSDN通过智能技术生成

解决java 8 stream toMap key的重复问题

问题描述

工作中遇到需要将某个List里面的实体类的两个属性对应起来,比如根据姓名找到年龄,就是将List里面的entity属性解析之后放到Map里。
实体类:

public class Person {
        private String name;
        private Integer age;
        ...省略getter、setter
    }

逻辑:

		Person person = new Person("张三",20);
        Person person1 = new Person("李四",20);
        Person person2 = new Person("张三",20);

        List<Person> list = new ArrayList<Person>(){{
            add(person);
            add(person1);
            add(person2);
        }};

        Map<String, Integer> map = new HashMap<>();
        //常规写法
        for (Person p : list) {
            map.put(p.getName(), p.getAge());
        }
        System.out.println(map);
        //stream 流写法
        Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Person::getName, Person::getAge));
        System.out.println(collect);

单纯常规写法肯定没什么问题,就是后面的key会被覆盖,但是stream流不行,会报错。

Exception in thread "main" java.lang.IllegalStateException: Duplicate key 20

原因分析:

Collectors.toMap这个方法其实是有三个参数的,第一个是key,第二个是value,第三个是发生冲突的合并规则。
默认采用的就是冲突之后抛出异常的处理。

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);
    }

解决方案:

只需要加上第三个参数即可

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);
    }

新代码只需要更改第三个参数即可,会跟常规写法一个效果

        Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Person::getName, Person::getAge, (oldValue, newValue) -> newValue));

当然还可以采用Collectors.groupingBy(keyFunction)的写法,但是返回值会是Map<key, List<value>>的形式。这就是新的业务场景了。
附上代码:

Map<String, List<Person>> collect1 = list.stream().collect(Collectors.groupingBy(Person::getName));
  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦幻D开始

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值