일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Java8
- Design Pattern
- domain
- 디자인 패턴
- Java 8 in action
- 클린코드
- spring
- head first
- Template Method Pattern
- jsp
- Java
- 스트림
- 자바
- CQRS
- 자바8
- Stream
- Java8 in action
- Was
- spring boot
- 패스트캠퍼스
- Java in action
- ddd
- facade pattern
- SERVLET
- AWS101
- Clean Code
- web
- 자바의 신
- 자바8인액션
- spring Batch
- Today
- Total
주난v 개발 성장기
[자바 8인 액션] 6장. 스트림으로 데이터 수집 본문
스트림의 연산은 filter, map과 같은 중간 연산 / count, findFirst, forEach, reduce 등의 최종 연산
중간 연산 : 한 스트림을 다른 스트림으로 변환, 여러 연산을 연결할 수 있다.
최종 연산 : 스트림 요소를 소비해서 최종 결과를 도출
컬렉터란?
스트림의 요소를 어떤 식으로 도출할지 지정
.collect(Collectors.toList());
collect를 호출하면 스트림의 요소에 리듀싱 연산이 수행된다.
collect에서는 리듀싱 연산을 이용해서 스트림의 각 요소를 방문하면서 컬렉터가 작업을 처리한다.
Collector 인터페이스의 메서드를 어떻게 구현하느냐에 따라 스트림에 어떤 리듀싱 연산을 수행할지 결정
Collectors 클래스는 정적 팩토리 메서드를 제공한다.
리듀싱과 요약
- 스트림의 항목을 컬렉션으로 재구성할 수 있다. (즉, 컬렉터로 스트림의 모든 항목을 하나의 결과로 합칠 수 있다.)
- 요약 : Collectors.maxBy, Collectors.minBy를 이용해서 최대 최소 혹은 합계 평균을 반환하는 리듀싱 기능이 자주 사용 -> 요약 연산
(summingInt, summingDouble...)
문자열 연결
- joining
String shortMenu = menu.stream().map(Dish::getName).collect(joining(",");
지금까지 살펴본 스트림 요소 수 계산, 최대 최소 합계 평균 등의 컬렉터는 reducing 팩토리 메서드로도 정의 가능 (즉, Collectors.reducing)
collect vs reduce
collect 대신 reduce를 사용할 수 있다.
collect 도출하려는 결과를 누적하는 컨테이너를 변경
reduce 두 값을 하나로 도출하는 불변형 연산....의미론적인 문제
여러 스레드가 동시에 같은 데이터 구조체를 고치면 리스트 자체가 망가져버리므로 리듀싱 연산을 병렬로 수행할 수 없다.
따라서 가변 컨테이너 작업이면서 병렬성을 확보하려면 collect 메서드로 reducing 연산을 구현해라.
그룹화
Collectors.groupingBy
Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collect(groupingBy(Dish::getType));
{FISH = [prawns, salmon], OTHER = [...], MEAT = [...]}
Dish.Type으로 일치하는 모든 요리를 추출해서 그룹화되므로 이를 분류 함수라 한다.
다수준 그룹화
- Collectors.groupingBy는 일반적인 분류 함수와 컬렉터를 인수로 받는다.
Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloricLevel =
menu.stream.collect(
groupingBy(Dish::getType,
groupingBy(dish -> {
if (dish.getCalories() <= 400) {
return CaloricLevel.DIET;
} else if (dish.getCalories() <= 700) {
return CaloricLevel.NORMAL;
} else {
return CaloricLevel.FAT;
}
})
)
);
Map<Dish.Type, Long> typesCount = menu.stream().collect(groupingBy(Dish::getType, counting());
컬렉터 결과를 다른 형식에 적용하기
- Collectors.collectingAndThen으로 컬렉터가 반환한 결과를 다른 형식으로 활용할 수 있다.
Map<Dish.Type, Long> typesCount =
menu.stream().collect(groupingBy(Dish::getType,
collectingAndThen(maxBy(compaingInt(Dish::getCalories)),Optional::get)));
분할
분할 함수
- 프레디케이트를 분류 함수로 사용하는 특수한 그룹화 기능
Map<Boolean, List<Dish>> partitionedMenu = menu.stream().collect(partitioningBy(Dish::isVegetarian));
분할의 장점
- 참, 거짓 두 가지 요소의 스트림 리스트를 모두 유지 (false = [], true = [] 두 수준의 맵이 반환)
Collector 인터페이스
- Collector 인터페이스는 리듀싱 연산을 어떻게 구현할지 제공하는 메서드 집합
(toList, groupingBy, ...)
Collector 인터페이스의 메서드
1. supplier : 빈 결과로 이루어진 Supplier 반환
2. accumulator : 결과 컨테이너에 요소 추가 (list.add)
3. finisher : 최종 변환값을 결과 컨테이너로 적용
4. combiner : 두 결과 컨테이너 병합
요약
-
collect는 스트림의 요소를 요약 결과로 누적하는 다양한 방법을 인수로 갖는 최종 연산이다.
-
스트림의 요소를 하나의 값으로 리듀스하고 요약하는 컬렉터 뿐 아니라 최대 / 최소 / 평균을 계산하는 컬렉터도 정의되어 있다.
-
groupingBy로 스트림의 요소를 그룹화하거나, partitioningBy로 요소를 분할 할 수 있다.
-
커스텀 컬렉터를 개발할 수 있다.
'개발 성장기 > JAVA' 카테고리의 다른 글
[자바 8인 액션] 7장. 병렬 데이터 처리와 성능 (0) | 2020.07.26 |
---|---|
[자바 8인 액션] 5장. 스트림 활용 (0) | 2020.07.15 |
[자바 8인 액션] 4장. 스트림 소개 (0) | 2020.07.05 |
[자바 8인 액션] 3장. 람다 표현식 (0) | 2020.07.01 |
[자바 8 인 액션] 2장. 동작 파라미터화 코드 전달 (0) | 2020.06.17 |