解决使用stream将list转map时,key重复导致报错的问题

 更新时间:2021年6月10日 15:00  
这篇文章主要介绍了解决使用stream将list转map时,key重复导致报错的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

要将List对象集合转为map集合,可以通过stream流的形式快速实现转换:

//三个Users对象组成一个List集合
List<Users> list = new ArrayList<>();
list.add(Users.builder().userName("11").userId(1).build());
list.add(Users.builder().userName("11").userId(2).build());
list.add(Users.builder().userName("33").userId(3).build());
//将list转map
Map<String, Users> usersMap = list.stream()
    .collect(Collectors.toMap(Users::getUserName, user -> user));
System.out.println(usersMap.get("11"));

但是上述代码运行后报了异常:

意思为map中出现了重复的key,也就是说通过上述方法转map时,出现重复key并不会出现覆盖的情况,而是再次在map中添加一个重复的key,导致报错。

所以通过stream实现list转map时,要实现重复的key会被覆盖,可以使用Function.identity()方法:

//三个Users对象组成一个List集合
List<Users> list = new ArrayList<>();
list.add(Users.builder().userName("11").userId(1).build());
list.add(Users.builder().userName("11").userId(2).build());
list.add(Users.builder().userName("33").userId(3).build());
//将list转map,这里是出现重复key时,覆盖前一个
Map<String, Users> usersMap = list.stream()
    .collect(Collectors.toMap(Users::getUserName, Function.identity(), (user1, user2) -> user2));
System.out.println(usersMap.get("11"));
//输出结果:
[email protected]

JDK 8 Stream List转换为Map的duplicate Key异常

Stream List to Map

Stream提供了List转换为Map提供了非常易用的方法:

Collectors.java:

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

其在转换过程中,会抛出异常:

 @Test(expected = IllegalStateException.class)
    public void testStreamMap_duplicateKey() {
        Employee employee = Employee.builder().id(1).age(20).firstName("zhang").build();
        Employee employee1 = Employee.builder().id(2).age(21).firstName("Li").build();
        Employee employee2 = Employee.builder().id(3).age(22).firstName("Li").build();
        Employee employee3 = Employee.builder().id(4).age(23).firstName("Chen").build();
        List<Employee> employees = Lists.newArrayList();
        employees.add(employee);
        employees.add(employee1);
        employees.add(employee2);
        employees.add(employee3);
        Map<String, Integer> dataMap = employees.stream().collect(Collectors.toMap(e -> e.getFirstName(), e -> e.getAge()));
        //Duplicate Key
        Map<Integer, Employee> employeeMap = employees.stream().collect(Collectors.toMap(e->e.getAge(), e->e));
    }

抛出异常信息:

java.lang.IllegalStateException: Duplicate key 21
 at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
 at java.util.HashMap.merge(HashMap.java:1254)
 at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
 at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
 at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
 at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
 at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
 at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
 at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
 at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
 at org.cjf.java.learn.jdk8.StreamTest.testStreamMap_duplicateKey(StreamTest.java:90)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
 at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
 at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
 at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
 at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
 at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
 at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Process finished with exit code 255

如何解决

增加重复key情况下的冲突处理策略:

 Map<String, Integer> dataMap = employees.stream().collect(Collectors.toMap(e -> e.getFirstName(), e -> e.getAge(), (k1, k2)-> k1));
        Assert.assertThat(dataMap, hasKey("zhang"));
        Assert.assertThat(dataMap, hasKey("Li"));
        Assert.assertThat(dataMap, hasKey("Chen"));
        Assert.assertThat(dataMap.keySet(), hasSize(3));
        Map<Integer, Employee> employeeMap = employees.stream().collect(Collectors.toMap(e->e.getAge(), e->e, (k1, k2) -> k1));
        Assert.assertThat(dataMap.keySet(), hasSize(3));

这里的处理策略是:

(k1, k2) -> k1

总结

在Collectors.toMap()转换过程中,需要注意一下duplicate key的处理逻辑,需要增加mergeFunction()处理方法。以上为个人经验,希望能给大家一个参考,也希望大家多多支持猪先飞

相关文章

  • 手把手带你了解Java-Stream流方法学习及总结

    这篇文章主要介绍了通过实例了解JavaStream流的方法学习和总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2021-08-19
  • Mybatis 复杂对象resultMap的使用

    这篇文章主要介绍了Mybatis 复杂对象resultMap的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-25
  • Java 数组转List的四种方式小结

    最近看了下数组转List的实现方法,总共有4种,本文就详细的介绍一下,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-06
  • springboot 中 inputStream 神秘消失之谜(终破)

    这篇文章主要介绍了springboot 中 inputStream 神秘消失之谜,为了能够把这个问题说明,我们首先需要从简单的http调用说起,通过设置body等一些操作,具体实现代码跟随小编一起看看吧...2021-08-07
  • mybatis mapper互相引用resultMap启动出错的解决

    这篇文章主要介绍了mybatis mapper互相引用resultMap启动出错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-25
  • 解决resultMap映射数据错误的问题

    这篇文章主要介绍了解决resultMap映射数据错误的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-25
  • java中Hashmap的get方法使用

    这篇文章主要介绍了java中Hashmap的get方法使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-13
  • 关于JAVA8的 Stream学习

    这篇文章主要介绍了JAVA8 Stream学习方法的相关资料,需要的朋友可以参考下面文章内容...2021-09-04
  • C++模拟实现list功能

    list的底层是一个循环双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。这篇文章主要介绍了C++模拟实现list,需要的朋友可以参考下...2021-08-11
  • python实现跳表SkipList的示例代码

    这篇文章主要介绍了python实现跳表SkipList的示例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-07-25
  • 关于Java Guava ImmutableMap不可变集合源码分析

    这篇文章主要介绍Java Guava不可变集合ImmutableMap的源码分析的相关资料,需要的朋友可以参考下面具体的文章内容...2021-09-07
  • HashMap原理及put方法与get方法的调用过程

    这篇文章主要介绍了HashMap原理及put方法与get方法的调用过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-09-13
  • 关于python类SortedList详解

    这篇文章主要介绍了关于python类SortedList详解,可以帮大家巩固一下python类的基础知识,有需要的朋友可以借鉴参考下,希望可以对广大读者有所帮助...2021-09-04
  • 在Map中实现key唯一不重复操作

    这篇文章主要介绍了在Map中实现key唯一不重复操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-08-29
  • 浅谈Vue3中key的作用和工作原理

    本文主要介绍了Vue3中key的作用和工作原理,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-08-08
  • Java之HashMap案例详解

    这篇文章主要介绍了Java之HashMap案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-11