9.1 그룹화
1. Collectors.groupingBy
데이터를 하나의 카테고리를 주제로 분류하고 싶을 경우에는 Collectors의 groupingBy 메서드를 사용하면 됩니다.
Map<Category, List<Book>> bookesByCategory = bookshelf.stream().collect(groupingBy(Book::getCategory));
위와 같이 코드를 작성하면 Category 종류별로 관련된 책들의 리스트를 조회할 수 있습니다. 그러나 페이지에 따라 책이 가벼운지 무거운지 알고 싶은 경우에는 조금 더 복잡한 코드를 작성해야 합니다.
Map<Thickness, List<Book>> booksByThickness = bookshelf.stream()
.collect(groupingBy(book -> {
if (book.getPage() < 100) return Thickness.THIN;
if (book.getPage() < 300) return Thickness.NORMAL;
return Thickness.THICK;
}));
2. 그룹화된 요소 조작
Map<Category, List<Book>> booksByCategory =
bookshelf.stream().filter(book -> book.getPage() > 100)
.collect(groupingBy(Book::getCategory));
100 페이지가 넘는 책들에 대해서만 그룹화 작업을 하고 싶어서 위와 같은 코드를 작성할 경우 만약 Economy라는 카테고리가 있고 이 항목에 있는 모든 책들이 다 100 페이지를 넘기지 않는다면 Map에 Economy라는 키값이 존재하지 않는다는 문제가 발생합니다.
Map<Category, List<Book>> booksByCategory = bookshelf.stream()
.collect(groupingBy(Book::getCategory,
filtering(book -> book.getPage() > 100), toList()));
public static <T, K, A, D>
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream) {
return groupingBy(classifier, HashMap::new, downstream);
}
위와 같이 Collector 변수에 프레디케이트를 설정하면 속한 값이 없는 Category도 항목에 추가됩니다.
3. 다수준 그룹화
Map<Category, Map<Thickness, List<Book>> booksByCateogryThickness =
bookshelf.stream().collect(
groupingBy(Book::getCategory,
groupingBy(book -> {
if (book.getPage() < 100) return Thickness.THIN;
if (book.getPage() < 300) return Thickness.NORMAL;
return Thickness.THICK;
})
)
);
// {ECONOMY = {THIN=[book1, book2], NORMAL=[book3]}, SCIENCE = {THICK=[book4], THIN=[book5]}, ...}
grouping 내부에 grouping 메서드를 한 번 더 사용함으로써 n수준의 맵을 만들 수 있습니다.
4. 서브그룹으로 데이터 수집
public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}
groupingBy(classifier) 메서드가 groupingBy(classifier, toList())의 축약형인만큼 두 번째 매개변수의 인자를 바꿈으로써 그룹화 메서드의 다양한 활용을 할 수 있습니다.
Map<Category, Long> countsByCategory = bookshelf.stream()
.collect(Collectors.groupingBy(
Book::getCategory,
Collectors.counting()
));
이 외에도 toSet, summingInt, maxBy 등의 여러 활용을 할 수 있습니다.
'독서 > 모던 자바 인 액션' 카테고리의 다른 글
[자바] 스트림을 이용한 데이터 수집 - Collectors (1) | 2023.10.05 |
---|---|
[자바] 스트림(Stream) 활용 (1) | 2023.10.05 |
데이터 컬렉션의 반복 처리 - 스트림(Stream) (1) | 2023.09.26 |
람다 표현식을 더 간결하게 - 메서드 참조 (0) | 2023.09.25 |
함수형 인터페이스를 통한 람다의 활용 (0) | 2023.09.24 |