티스토리 뷰
728x90
반응형
그룹화
groupingBy() 연산의 결과로 그룹화 함수가 반환하는 키, 각 키에 대응하는 스트림의 모든 항목 리스트를 값으로 갖는 Map 반환
Map<Dish.Type, List<Dish>> dishesByType = menu.stream()
.collect(groupingBy(Dish::getType));
Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect( //복잡한 분류 기준이 필요한 상황
groupingBy(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
}));
그룹화된 요소 조작
- filtering()은 Predicate 인수로 각 그룹의 요소와 필터링 된 요소를 재그룹화
- 목록이 비어있는 항목도 추가
Map<Dish.Type, List<Dish>> caloricDishesByType = menu.stream().filter(dish -> dish.getCalories() > 500)
.collect(groupingBy(Dish::getType));
//{OTHER=[french fries, pizza], MEAT=[pork, beef]}, FISH 요리가 없으면 키 자체가 사라짐
Map<Dish.Type, List<Dish>> caloricDishesByType = menu.stream().collect(
groupingBy(Dish::getType,
filtering(dish -> dish.getCalories() > 500, toList())));
//{OTHER=[french fries, pizza], MEAT=[pork, beef], FISH=[]}
- mapping()은 매핑 함수와 각 항목에 적용한 함수를 모으는데 사용
Map<Dish.Type, List<String>> dishNamesByType = menu.stream().collect(
groupingBy(Dish::getType, mapping(Dish::getName, toList())));
- flatMapping()은 groupingBy 등의 메서드와 함께 사용되어 그룹화된 요소를 다시 플랫하게 변환할 때 유용
- 첫번째 인자는 각 요소를 스트림으로 변환하는 함수
- 두번째 인자는 첫번째 인자에서 반환된 스트림의 요소를 수집하는데 사용할 Collector
List<String> fruits = Arrays.asList("apple", "banana", "apricot", "grape", "blueberry");
// 각 과일을 길이에 따라 그룹화하고, 그룹화된 리스트를 플랫하게 변환하여 모든 과일을 하나의 리스트로 얻는다.
Map<Integer, List<String>> groupedByLength = fruits.stream()
.collect(Collectors.groupingBy(String::length,
Collectors.flatMapping(str -> Stream.of(str), Collectors.toList())));
System.out.println(groupedByLength);
//{5=[apple, grape], 6=[banana, apricot], 9=[blueberry]}
다수준 그룹화
- Collectors.groupingBy를 중첩하여 다수준 그룹화를 수행
- n 수준 그룹화의 결과는 n 수준 트리 구조로 표현되는 n 수준 맵이 됨
List<String> fruits = Arrays.asList("apple", "banana", "apricot", "grape", "blueberry");
// 먼저 길이로 그룹화하고, 그 다음 첫 번째 글자로 그룹화한다.
Map<Integer, Map<Character, List<String>>> groupedByLengthAndFirstChar = fruits.stream()
.collect(Collectors.groupingBy(String::length,
Collectors.groupingBy(str -> str.charAt(0))));
System.out.println(groupedByLengthAndFirstChar);
//{5={a=[apple], g=[grape]}, 6={b=[banana], a=[apricot]}, 9={b=[blueberry]}}
서브그룹으로 데이터 수집
- collectingAndThen()은 Collector가 수집한 결과에 추가적인 변환을 적용하여 최종 결과를 얻을 때 유용
Map<Dish.Type, Dish> mostCaloricByType = menu.stream().collect(
groupingBy(Dish::getType, //분류함수
collectionAndThen(
maxBy(comparingInt(Dish::getCalories)), //감싸인 컬렉터
Optional::get))); //변환 함수
- 같은 그룹으로 분류된 모든 요소에 리듀싱 작업을 수행할 때는 groupingBy에 두번째 인수로 전달한 컬렉터를 사용
Map<Dish.Type, Integer> totalCaloriesByType = menu.stream().collect( //각 요리 그룹의 칼로리 합계
groupingBy(Dish::getType,
summingInt(Dish::getCalories));
- mapping()은 스트림의 요소를 변환한 뒤 해당 변환된 결과를 다른 컬렉터로 수집하는 데 사용
- 변환 함수를 적용하여 스트림의 요소를 변환한 후, 해당 변환된 결과를 다른 컬렉터로 수집하는 기능을 제공
- 스트림의 요소를 변환하는 함수와 변환된 결과를 수집할 컬렉터를 인수로 받음
Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType = menu.stream().collect(
groupingBy(Dish::getType, mapping(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;},
toSet())));
- toCollection()은 지정된 컬렉션 타입에 요소를 수집하는 데 사용
Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType = menu.stream().collect(
groupingBy(Dish::getType, mapping(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;},
toCollection(HashSet::new) )));
728x90
반응형
'Java' 카테고리의 다른 글
[Java] Stream 병렬 데이터 처리와 성능 (0) | 2023.08.15 |
---|---|
[Java] 스트림으로 데이터 수집 - 분할 (0) | 2023.08.09 |
[Java] 스트림으로 데이터 수집 - 요약 연산 (0) | 2023.08.05 |
[Java] Stream (0) | 2023.07.31 |
동작 파라미터화 코드 전달하기 (0) | 2023.06.21 |
반응형
300x250