采坑系列 Collectors.toMap

java8出的流操作,由于可以快速转化为map并且便于代码阅读,所以推荐使用java8语法转化List为map。

这里给出例子:


public class GroupByTest {


    public class Student{
        private String name;
        private Integer age;

        public String getName() {
            return name;
        }

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

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public Student name(String name){
            this.name = name;
            return this;
        }

        public Student age(Integer age){
            this.age = age;
            return this;
        }




    }


    @Test
    public void groupBy(){

        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student().age(20).name("张三"));
        studentList.add(new Student().age(20).name("李四"));
        studentList.add(new Student().age(21).name("王五"));

        Map<Integer, Student> collect = studentList.stream().collect(Collectors.toMap(Student::getAge, v -> v));

    }
}

结果上诉代码报错

java.lang.IllegalStateException: Duplicate key com.example.demo.GroupByTest$Student@22680f52

	at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
	at java.util.HashMap.merge(HashMap.java:1254)

 

分析原因:

Collectors源码 

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

merge方法源码

 

上面的源码可以看到。

Collectors.toMap 传入了一个  参数 
throwingMerger() 

我们看这个方法中代码,发现直接扔了一个异常。 

    private static <T> BinaryOperator<T> throwingMerger() {
        return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
    }
remappingFunction 一直传到了merge 方法中 。
  • 判断key对应的value是否有值,如果有值,执行 入参 remappingFunction 的操作。但是我们传入的是 抛出异常,所以。这里直接抛出了异常;

我们打断点调试看到 

 

解决方法,调用重载方法

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

自己传入 function 

可以看到,这里已经对重复值进行了覆盖。

 

解决方案:调用重载方法,传入处理的 function

Collectors.toMap(Student::getAge, v -> v, (u, v) -> v)

 

总结:使用api时,如果遇到重载的api,需要搞清楚可能会发生的问题,每个参数的含义。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java 开发者 配置jdk1.8 一下是jdk1.8的新特性Lamdbd表达式 forEach循环遍历 List<String> names = new ArrayList(); names.forEach(String x -> { System.out.println(x); System.out.println(x); }); Map<String,String> map = new HashMap(); map.forEach((x,y) -> System.out.println(x+":"+y)); 集合里放对象 List<Book> books; books.forEach(x -> System.out.println(x.getBookName())); List<Map> books = new ArrayList(); Map map = new HashMap(); map.put("name","aaa"); map.put("price",33); books.forEach(x -> x.forEach(y,z) -> System.out.println(y+":"+z)); 方法引用 names.forEach(System.out::println); 等同于 names.forEach(x->System.out.println(x)) removeIf 条件移除 List<Book> books; books.removeIf(x -> x.getBookPrice() > 22); stream 对集合进行处理,并不会改变集合,类似于数据库的select 创建stream 集合.stream() 操作stream filter 过滤 map 转换 skip 跳过 distinct 去重 limit 取几条 结果处理 foreach 输出 collect 收集 count 总条数 List<String> names = ; names.add("zhangsan"); names.add("zhangsan"); List nNews = names.stream.distinct().collect(Collectors.toList()); Collectors.toSet() //取出名字长度大于4的,跳过第1个,取2个 List<String> nNames = names.stream.filter(x->x.length()>4).skip(1),limt(2).collect(Collectors.toList()); //把长度转换成一个集合 List<Integer> c = names.stream.map(x->x.length()).collect(Collectors.toList()); List<Integer> c = names.stream.map(String::length).collect(Collectors.toList());

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值