ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Stream(스트림) - 5. 최종 연산 1/3
    Java 2020. 3. 10. 22:04
    반응형

    최종 연산

     최종 연산은 스트림의 요소를 소모해서 결과를 만들어 냄 = 최종 연산 후에는 스트림이 닫히고 사용할 수 없음

     최종 연산의 결과 = 스트림 요소의 합과 같은 단일 값 or 스트림이 담긴 배열 또는 컬렉션

     forEach(), count(), ... collect() 등이 있음

    forEach()

     peek()과 달리 스트림의 요소를 소모하는 최종 연산

     반환 타입은 void이므로 스트림의 요소를 출력하는 용도로 많이 사용됨

    - forEach 사용 지양 참고

    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값 리턴
    }

     

    반응형

    댓글

Designed by Tistory.