일반적으로 Stream을 사용할 때 map으로 변환하기 위해 Collectors.toMap
을 사용한다.
예를 들어 아래의 코드가 있다고 해보자
public class User {
private String id;
private String name;
}
List<User> users = Arrays.asList(
new User("hong", "홍길동"),
new User("lee", "이승엽"),
new User("kim", "김기동")
);
toMap의 기본 사용법
users List를 id와 name을 가진 map으로 변환을 하려면 아래와 같이하면 된다.
Map<Integer, String> userMap = users.stream()
.collect(Collectors.toMap(User::getId, User::getName));
System.out.println(userMap); // {hong=홍길동, lee=이승엽, kim=김기동}
System.out.println(userMap.get("hong")); // 홍길동
Function.identity() 사용법
하지만 map의 value에 name이 아닌 User 객체를 넣고 싶을 경우에는 어떻게 해야 할까?
Function.identity()
를 사용하면 된다.
Map<String, User> userMap2 = users.stream()
.collect(Collectors.toMap(User::getId, Function.identity()));
System.out.println(userMap2); // {hong=FunctionSample.User(id=hong, name=홍길동), lee=FunctionSample.User(id=lee, name=이승엽), kim=FunctionSample.User(id=kim, name=김기동)}
System.out.println(userMap2.get("hong")); // FunctionSample.User(id=1, name=홍길동)
System.out.println(userMap2.get("hong").getName()); // 홍길동
키 중복이 생기는 경우
만일 id의 길이로 toMap을 하면 어떻게 될까?
4=홍길동, 3=이승엽, 3=김기동으로 표시될 것 같은데 한번 실행해보자.
Map<Integer, User> userMap = users.stream()
.collect(Collectors.toMap(
user -> user.getId().length(),
Function.identity()
));
System.out.println(userMap);
실행하면 아래와 같은 오류가 발생한다.
Exception in thread "main" java.lang.IllegalStateException: Duplicate key FunctionSample.User(id=lee, name=이승엽)
키 중복 해결법
toMap 시 중복키에 대한 오류를 방지하기 위한 해결책도 이미 가지고 있다.
Map<Integer, User> userMap = users.stream()
.collect(Collectors.toMap(
user -> user.getId().length(),
Function.identity(),
(oldValue, newValue) -> oldValue) // 기존값, 새로운 값 중 선택을 할 수 있다.
);
System.out.println(userMap);
위에서 (oldValue, newValue)으로 기존값이나 새로운값으로 선택을 할 수 있는 옵션이 있다. 여기서는 기존값(oldValue)로 선택을 했다.
이렇게 실행하면 아래와 같은 결과가 표시된다.
{3=FunctionSample.User(id=lee, name=이승엽), 4=FunctionSample.User(id=hong, name=홍길동)}
이승엽(기본값), 김기동(새로운 값) 중 이승엽으로 출력이 된다.
반응형