Java

[Java] Collectors.toMap() 변환 시 IllegalStateException 에러 발생 이유

haehyun 2021. 12. 15. 16:09
728x90

에러

Stream<Student> 타입을 Map<String, Student> 로 변환하는 과정에서 IllegalStateException 예외가 발생한다.

Student[] stuArr = {
                new Student("이자바", 3, 300),
                new Student("김자바", 1, 200),
                new Student("안자바", 2, 100),
                new Student("박자바", 2, 150),
                new Student("나자바", 3, 290),
                new Student("김자바", 3, 180)
        };

Map<String, Student> stuMap = Stream.of(stuArr)
                .collect(Collectors.toMap(s -> s.getName(), p->p));
Exception in thread "main" java.lang.IllegalStateException: Duplicate key [김자바, 1, 200]
	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.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	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 ch14.StreamEx6.main(StreamEx6.java:32)

 

원인

Map<String, Student> 로 변환하는 과정에서 스트림의 요소인 Student 객체의 name 멤버를 Key로 지정했는데, 객체들 간에 이 값이 중복되는 요소가 있어 키(Key)가 중복된 것.
Map<Key, Value> 타입은 Value는 중복을 허용하나, Key는 중복을 허용하지 않는다.

해결

테스트용 Student[] 배열에서 name 값이 겹치는 요소의 값을 변경해준다.

Student[] stuArr = {
        new Student("이자바", 3, 300),
        new Student("김자바", 1, 200),
        new Student("안자바", 2, 100),
        new Student("박자바", 2, 150),
        new Student("나자바", 3, 290),
        new Student("강자바", 3, 180)
};

// 스트림을 Map<String, Student> 로 변환, 학생이름이 key
Map<String, Student> stuMap = Stream.of(stuArr)
        .collect(Collectors.toMap(s -> s.getName(), p->p));

 

이때 Student 객체 그 자체를 가리키는 항등 함수는 람다식 p->p 대신 Function.identity()를 써도 된다.

// 스트림을 Map<String, Student> 로 변환, 학생이름이 key
Map<String, Student> stuMap = Stream.of(stuArr)
        .collect(Collectors.toMap(s -> s.getName(), Function.identity()));
728x90