一、异常现象和问题描述
在进行将流规约处理为Map时出现冲突导致规约合并失败异常导致流规约异常,异常现象为抛出合并异常,如下:
运行抛出异常:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 28
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1253)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
二、代码复现如下:
//员工列表
List<Employee> employList = new ArrayList<Employee>();
//添加员工
employList.add(new Employee(20200401, "Mike", 25));
employList.add(new Employee(20200402, "Mary", 26));
employList.add(new Employee(20200403, "Jack", 28));
employList.add(new Employee(20200404, "Tom", 23));
employList.add(new Employee(20200405, "Lucy", 21));
employList.add(new Employee(20200406, "Jim", 26));
employList.add(new Employee(20200407, "David", 29));
employList.add(new Employee(20200408, "Jack", 22));
/**
* 将员工列表规约处理为姓名和年龄集合,由于员工有重名,符合规约异常问题现象复现
*/
//异常规约处理方式,不进行出现重名时的处理---出现规约冲突异常;
Map<String, Integer> nameAgeIgnoreRepeatMap = employList.stream().collect(Collectors.toMap(Employee :: getName, Employee :: getAge));
//对重名现象进行处理,避免规约冲突;“(v1, v2) -> v1”,当出现冲突时默认取初始出现值;实际中可以根据自己的实际情况取值
Map<String, Integer> nameAgeMap = employList.stream().collect(Collectors.toMap(Employee :: getName, Employee :: getAge, (v1, v2) -> v1));
三、解决方法,规约处理时进行冲突兼容处理,即出现冲突时进行取值选择
冲突处理选择方法,在toMap(key, value, (v1,v2) -> v1)中添加冲突时选值参数“(v1, v2)-> v1”表示出现key冲突时取第一次出现的key的值,,“(v1, v2)-> v2”表示出现key冲突时取最后一次出现的key的值,在实际中根据自己的实际情况取值。使用示例如下所示:
//对重名现象进行处理,避免规约冲突;“(v1, v2) -> v1”,当出现冲突时默认取初始出现值;实际中可以根据自己的实际情况取值
Map<String, Integer> nameAgeMap = employList.stream().collect(Collectors.toMap(Employee :: getName, Employee :: getAge, (v1, v2) -> v1));
以上为实际中遇到的问题,写下解决思路,供参考,有不对的地方,欢迎指正,共同学习,共同进步!