解决异常:java.lang.IllegalStateException: Duplicate key **
最近在项目中使用java8的list 转 map的时候遇到了重复值的异常:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key Person@568db2f2 at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133) at java.util.HashMap.merge(HashMap.java:1245) at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320) at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
1、写了测试类重现异常:
在业务场景中出现重复值的时候我们希望使用新的值替换之前的值:
public static void main(String[] args) { Person a1= new Person("p","p1"); Person a2= new Person("p","p2"); Person a3= new Person("p1","p3"); List<Person> list = new ArrayList<Person>(); list.add(a1); list.add(a2); list.add(a3); //下面这句会出异常java.lang.IllegalStateException: Duplicate key Map<String, Person> map1 = list.stream().collect(Collectors.toMap(Person::getName , (p) -> p)); } class Person { private String name; private String sex; public Person(String name, String sex) { super(); this.name = name; this.sex = sex; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
这段代码会抛出开头贴出来的异常:java.lang.IllegalStateException: Duplicate key **
总结一下:
使用Collectors.toMap方法时的两个问题:
1、当key重复时,会抛出异常:java.lang.IllegalStateException: Duplicate key **
2、当value为null时,会抛出异常:java.lang.NullPointerException
大家通常希望这个方法是可以容错的,遇到重复的key就使用后者替换,而且HashMap的value可以是null。
将之前出错的代码调整如下:
//下面这句会出异常java.lang.IllegalStateException: Duplicate key Map<String, Person> map1 = list.stream().collect(Collectors.toMap(Person::getName , (p) -> p)); //修改为下面这句 Map<String, Person> map2 = list.stream().collect(Collectors.toMap(Person::getName , (p) -> p,(k,v)->v));
记录一下:
//1.针对重复key的 覆盖之前的value list.stream().collect(Collectors.toMap(Person::getName, Person::getSex,(k,v)->v)); //2.value为空,直接存放 不调用map.merge。同样适用于1(key重复的情况) list.stream().collect(Collector.of(HashMap::new, (m,per)->m.put(per.getName(),per.getSex()), (k,v)->v, Characteristics.IDENTITY_FINISH)); //其中lambda表达式: (k,v)->v 不会被调用,但是又不能为空