-
Stream(스트림) - 5. 최종 연산 1/3Java 2020. 3. 10. 22:04반응형
최종 연산
최종 연산은 스트림의 요소를 소모해서 결과를 만들어 냄 = 최종 연산 후에는 스트림이 닫히고 사용할 수 없음
최종 연산의 결과 = 스트림 요소의 합과 같은 단일 값 or 스트림이 담긴 배열 또는 컬렉션
forEach(), count(), ... collect() 등이 있음
forEach()
peek()과 달리 스트림의 요소를 소모하는 최종 연산
반환 타입은 void이므로 스트림의 요소를 출력하는 용도로 많이 사용됨
void forEach(Consumer<? supter T> action)
조건 검사 : allMatch(), anyMatch(), noneMatch(), findFirst(), findAny()
스트림의 요소에 대해 지정된 조건에 모든 요소가 일치하는지, 일부가 일치하는지 아니면 어떤 요소도 일치하지 않는지 확인하는데 사용
모두 매개변수로 Predication를 요구, 연산 결과로 boolean 반환
boolean allMatch (Predicate<? super T> predicate) boolean anyMatch (Predicate<? super T> predicate) boolean noneMatch(Predicate<? super T> predicate)
findFirst() : 스트림의 요소 중 조건에 일치하는 첫 번째 것을 반환
- 주로 filter()와 함께 사용되어 조건에 맞는 스트림의 요소가 있는지 확인
findAny() : 병렬 스트림일 경우 findFirst() 대신 사용
findFirst() & findAny()
- 반환 타입 Optional<T>
- 스트림의 요소가 없을 때는 비어있는(내부적으로 null을 저장한) Optional 객체 반환
Optional<Student> student = studentStream.filter(s -> s.getTotalScore() <= 100) .findFirst(); Optional<Student> student = parallelStream.filter(s -> s.getTotalScore() <= 100) .findAny();
통계 : count(), sum(), average(), max(), min()
IntStream과 같은 기본형 스트림에는 스트림의 요소들에 대한 통계 정보를 얻을 수 있는 메서드들이 있음
기본형 스트림이 아닌 경우엔, 통계 관련된 메서드들은 3개 뿐임
- 기본형 스트림의 min(), max와 달리 매개 변수로 comparator를 필요로 함
- 대부분은 아래 메서드를 사용하기보단 기본형 스트림으로 변환하거나, reduce()와 collect()를 사용해서 통계 정보를 얻음
long count(); Optional<T> max(Comparator<? super T> comparator) Optional<T> min(Comparator<? super T>) comparator)
리듀싱 : reduce()
스트림의 요소를 줄여나가면서 연산을 수행하고 최종 결과를 반환
매개변수의 타입이 BinaryOperator<T>
처음 두 요소를 가지고 연산한 결과를 가지고 그 다음 요소와 연산, 그 과정에서 스트림의 요소를 하나씩 소모
> 전체 소모시 그 결과를 반환
Optional<T> reduce(BinaryOperator<T> accumulator)
이 외 연산결과의 초기값(identity)을 갖는 reduce()도 있음
- 초기값과 스트림의 첫 번째 요소로 연산을 시작
- 스트림의 요소가 하나도 없는 경우, 초기값이 반환되므로 반환 타입이 Optional<T>가 아닌 T임
BinaryOperator<T>는 BiFunction의 자손, BiFunction<T, T, T>와 동등
T reduce(T identity, BinaryOperator<T> accumulator) U reduce(U identity, BiFunction<U, T, U> accumulator, BinaryOperator<U> combiner)
위의 combiner - 병렬 스트림에 의해 처리된 결과를 합칠 때 사용하기 위해 사용하는 것
최종 연산인 count()와 sum() 등은 모두 내부적으로 reduce()를 이용해서 아래와 같이 작성
- max()/min()은 초기값이 필요하지 않으므로 Optional<T>를 반환하는 매개변수 하나짜리 reduce()를 사용하는 것이 좋음
int count = intStream.reduce(0, (a, b) -> a + 1); // count() int sum = intStream.reduce(0, (a, b) -> a + b); // sum() int max = intStream.reduce(Integer.MIN_VALUE, (a, b) -> a > b ? a : b); // max() int min = intStream.reduce(Integer.MAX_VALUE, (a, b) -> a < b ? a : b); // min()
intStream의 타입이 IntStream인 경우 OptionalInt를 사용해야 함
- Stream<T>와 달리 IntStream에 정의된 reduce의 반환 타입은 OptionalInt이기 때문
// OptionalInt reduce(IntBinaryOperator accumulator) OptionalInt max = intStream.reduce((a, b) -> a > b ? a : b); // max() OptionalInt min = intStream.reduce((a, b) -> a < b ? a : b); // min()
위를 Integer 클래스의 static 메서드 max()와 min()을 이용한 메서드 참조로 바꾸면 아래와 같음
Optional max = intStream.reduce(Integer::max); // int max(int a, int b) Optional min = intStream.reduce(Integer::max); // int min(int a, int b)
OptionalInt에 저장된 값 꺼내기
int maxValue = max.getAsInt(); // OptionalInt의 값을 maxValue에 저장 int minValue = min.getAsInt(); // OptionalInt의 값을 minValue에 저장
reduce()의 구조
- 초기값(identity)과 어떤 연산(BinaryOperator)으로 스트림의 요소를 줄여나갈 것인지 결정
T reduce(T identity, BinaryOperator<T> accumulator) { T a = identity; // 초기값 for (T b : stream) a = accumulator.apply(a, b); // 모든 요소의 값을 a에 적용 return a; // 적용 a값 리턴 }
반응형'Java' 카테고리의 다른 글
Stream(스트림) - 7. Collector 구현 (최종연산 3/3) (0) 2020.03.11 Stream(스트림) - 6. collect() (최종연산 2/3) (0) 2020.03.11 Stream(스트림) - 4. Optional<T> & OptionalInt (0) 2020.03.10 Stream(스트림) - 3. 스트림 중간 연산 (0) 2020.03.09 Stream(스트림) - 2. 스트림 생성하기 (0) 2020.02.13