jdk8流处理toMap异常Duplicate key解决

背景

在开发过程中,我们经常要将list按照规则转为map,而jdk8提供了一个很好的工具:Collections.toMap,使用这个方法时,往往会有一些坑。

Collections.toMap示例

创建一个pojo

import java.io.Serializable;  import lombok.Data;  @Data public class Student implements Serializable{ 	private static final long serialVersionUID = 1L; 	//字段 	private Integer id; 	private String firstName; 	private String lastName; 	private Integer age; 	public static Student createStudent(Integer id,String firstName,String lastName,Integer age) { 		Student st=new Student(); 		st.id=id; 		st.firstName=firstName; 		st.lastName=lastName; 		st.age=age; 		return st; 	} 	@Override 	   public String toString() { 	    return "student [id=" + id + ", firstName=" + firstName 	    		 + ", lastName=" + lastName + ", age=" +age+ ']'; 	   } } 

创建测试类

import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors;  public class MapTest { 	 	public static void main(String[] args) { 		List<Student> sts=new ArrayList<Student>(); 		sts.add(Student.createStudent(1, "david", "wang", 20)); 		sts.add(Student.createStudent(2, "david1", "wang1", 21)); 		sts.add(Student.createStudent(2, "david2", "wang2", 22)); 		Map<Integer,Student> id_student=sts.stream().collect(Collectors.toMap(Student::getId, student ->student)); 		System.out.println("Collections.toMap test:"+id_student.get(2).getFirstName());  	} }

报错信息:

Exception in thread "main" java.lang.IllegalStateException: Duplicate key student [id=2, firstName=david1, lastName=wang1, age=21] 	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) 	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374) 	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 MapTest.main(MapTest.java:13)

解决方法

保留1:

import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors;  public class MapTest { 	 	public static void main(String[] args) { 		List<Student> sts=new ArrayList<Student>(); 		sts.add(Student.createStudent(1, "david", "wang", 20)); 		sts.add(Student.createStudent(2, "david1", "wang1", 21)); 		sts.add(Student.createStudent(2, "david2", "wang2", 22)); 		Map<Integer,Student> id_student=sts.stream().collect(Collectors.toMap(Student::getId, student -> student,(v1,v2) -> v1)); 		System.out.println("Collections.toMap test:"+id_student.get(2).getFirstName());  	} } 

结果

Collections.toMap test:david1

保留2:

import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors;  public class MapTest { 	 	public static void main(String[] args) { 		List<Student> sts=new ArrayList<Student>(); 		sts.add(Student.createStudent(1, "david", "wang", 20)); 		sts.add(Student.createStudent(2, "david1", "wang1", 21)); 		sts.add(Student.createStudent(2, "david2", "wang2", 22)); 		Map<Integer,Student> id_student=sts.stream().collect(Collectors.toMap(Student::getId, student -> student,(v1,v2) -> v2)); 		System.out.println("Collections.toMap test:"+id_student.get(2).getFirstName());  	} } 

结果

Collections.toMap test:david2

结论

    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的Key,例如上面例子中用ManualEntry的Id做key;

第二个参数为map的value,例如例子中要生成的value为manualEntry.getGroupInsIds()分割后组成的List的合集

第三个参数则为key重复时处理方法:例子中的处理方式是如果重复,使用value2,即覆盖,也可以做其他处理

您可能还会对下面的文章感兴趣: