기본 패턴
java
Map<String, List<Student>> byDepartment =
students.stream()
.collect(Collectors.groupingBy(Student::getDepartment));설명
- Stream에서 terminal operation은 단순히 끝내는 단계가 아니라, 결과의 모양을 결정하는 단계이기도 합니다. 이 역할을 가장 많이 맡는 것이
Collectors입니다. groupingBy는 분류 기준에 따라 여러 값을 묶어Map<K, List<T>>형태를 만들고, 필요하면 downstream collector를 붙여counting,mapping,averagingInt같은 추가 집계를 연결할 수 있습니다.toMap은 한 항목을 key-value로 변환해 맵을 만들 때 쓰지만, key 충돌이 날 수 있다는 점이 중요합니다. 충돌 정책 없이 무심코 쓰면 런타임 예외가 날 수 있습니다.- 이 카드의 핵심은 "수집의 설계"입니다. Stream 중간 단계가 데이터를 어떻게 흘려 보낼지 정한다면, collector는 마지막에 어떤 구조로 정착시킬지 결정합니다.
- 좋은 Stream 코드는 filter-map까지만 깔끔한 것이 아니라, 마지막 수집 구조까지 도메인에 잘 맞아야 합니다. 결국 리포트, 인덱싱, lookup map, 그룹 집계가 여기서 결정됩니다.
빠른 정리
| collector | 역할 |
|---|---|
toList() | 리스트로 수집 |
toSet() | 집합으로 수집 |
groupingBy(...) | 키 기준 그룹화 |
toMap(...) | 맵으로 수집 |
| downstream collector | 그룹 결과를 추가 집계 |
주의할 점
toMap은 key가 겹칠 수 있는 데이터에 그대로 쓰면 예외가 날 수 있습니다. key 충돌 가능성이 있다면
merge 함수가 필요한지 먼저 생각하는 편이 안전합니다.
참고 링크
2 sources