[Java] Stream의 reduce()와 BinaryOperator

Jiwoo Kim·2021년 8월 24일
3

머리에 자바 넣기

목록 보기
4/4
post-thumbnail

Stream을 사용하다가 reduce()와 파라미터들에 대해 스스로 이해가 부족하다고 느껴 다시 한 번 정리한다.


BinaryOperator

Represents an operation upon two operands of the same type, producing a result of the same type as the operands. This is a specialization of BiFunction for the case where the operands and the result are all of the same type.

BinaryOperator는 같은 타입의 파라미터 2개를 받아 결과값을 리턴하는 functional interface다. 주로 람다메서드 참조를 위해 사용된다. 그냥 식을 적는 것보다 가독성이 좋기 때문에 적극 활용하는 것이 좋다.

또한, BiFunction을 상속하는 인터페이스로서, apply(T t, U u) 메서드를 호출해서 function을 적용한다.

IntBinaryOperator

IntBinaryOperatorint 타입의 파라미터 2개를 받아 int 타입의 결과값을 리턴한다.

이름에서 알 수 있듯이 BinaryOperator를 상속하며, applyAsInt(int left, int right)는 내부적으로 BiFunctionapply(T t, U u)를 호출한다.

아래 reduce() 설명 예시는 모두 IntStreamIntBinaryOperator를 사용했다.


reduce()

우선, reduce()는 스트림의 원소들을 하나씩 소모해가며, 누적 계산을 수행하고 결과값을 리턴하는 메서드다.

reduce()는 파라미터를 3개 받을 수 있다.

  • T identity: 계산에 적용할 초깃값으로, 스트림이 비어 있더라도 초깃값을 반환
  • BinaryOperator<T> accumulator: 적용할 계산 함수
  • BinaryOperator<U> combiner: 병렬 스트림에서 각 쓰레드 계산 결과를 합치는 함수

파라미터 1개

Optional<T> reduce(BinaryOperator<T> accumulator)

아래와 같이 스트림의 모든 element를 차례로 돌면서 accumulator를 적용하며 result를 갱신한다.
스트림이 비어 있으면 Optional.empty()를 반환한다.

boolean foundAny = false;
T result = null;
for (T element : this stream) {
    if (!foundAny) {
        foundAny = true;
        result = element;
    } else
        result = accumulator.apply(result, element);
    }
return foundAny ? Optional.of(result) : Optional.empty();

사용 예시는 아래와 같다.

OptionalInt result = IntStream.of(1, 2, 3)
    .mapToInt(value -> value + 1)
    .reduce((a,b) -> a+b);

result.getAsInt();	// 6

파라미터 2개

T reduce(T identity, BinaryOperator<T> accumulator)

결과의 초깃값을 identity로 설정한 후, 스트림의 모든 element를 차례로 돌면서 accumulator를 적용하며 result를 갱신한다.
스트림이 비어 있어도 초깃값인 identity를 반환한다.

T result = identity;
for (T element : this stream)
    result = accumulator.apply(result, element)
return result;

사용 예시는 아래와 같다.

int result = IntStream.of(3, 4, 5)
    .reduce(1, (a,b) -> a*b);	// 60

파라미터 3개

<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)

U result = identity;
for (T element : this stream)
    result = accumulator.apply(result, element)
return result;

(수정필요)


참고

Java Platform SE 8 공식 API

1개의 댓글

comment-user-thumbnail
2022년 12월 22일

안녕하세요. 글 보다가 잘못된 내용이 있어서 댓글 남깁니다.

OptionalInt result = IntStream.of(1, 2, 3)
.mapToInt(value -> value + 1)
.reduce((a,b) -> a+b);

result.getAsInt(); // 6

  1. IntStream은 mapToInt 메서드가 없습니다, 굳이 mapToInt를 사용하려면, IntStream을 'Stream (Integer)'로 변환하는 boxed() 메서드를 사용해야 합니다.

OptionalInt result = IntStream.of(1, 2, 3).boxed()
.mapToInt(value -> value + 1)
.reduce((a,b) -> a+b);

  1. result.getAsInt(); 의 값은 9입니다.
답글 달기