모던 자바인 액션 ch5 - 스트림 활용

김진욱·2022년 9월 23일
0

java

목록 보기
5/13
post-thumbnail

스트림 슬라이싱

TAKEWHILE

  • Java 9에 추가된 메서드

  • Predicate<T>를 파라미터로 받아서 해당 Predicate가 false를 반환할 때까지의 요소를 취하는 메서드다.

  • 얼핏보면 filter 메서드와 유사해보이지만, filter 메서드가 전체 스트림에 대한 Predicate를 판단하는 반면 takeWhile은 Predicate가 false를 반환하는 순간 나머지 요소를 전부 버린다.

    • 아주 많은 요소를 가진 스트림에서는 이런 부분이 큰 차이를 유발할 수 있다.
    • 특히, 정렬되어 있는 요소에 대해서 큰 장점을 가질 수 있다.
  • 무한 스트림을 포함한 모든 스트림에 Predicate를 적용해 스트림을 슬라이스할 수 있다

DROPWHILE

  • Java 9에 추가된 메서드
  • Predicate<T>를 파라미터로 받아서 해당 Predicate가 false를 반환할 때까지의 요소를 모두 버리고 나머지 요소를 반환하는 메서드다.
  • takeWhile정반대로 작업을 수행한다.
  • Predicate가 false가 되는 지점에서 작업을 중단하고 남은 모든 요소를 반환한다.

LIMIT

  • 주어진 값 이하의 크기를 갖는 새로운 스트림을 반환하는 메서드
  • long을 파라미터로 받아서 해당 숫자 이하의 요소를 반환
  • 소스가 정렬되어 있지 않았다면 limit의 결과도 정렬되지 않은 상태로 반환된다.

SKIP

  • 처음 n개 요소를 제외한 스트림을 반환하는 메서드
  • long을 파라미터로 받아서 해당 숫자 이하의 요소를 버리고 나머지를 반환
  • n개 이하의 요소를 포함하는 스트림에 skip(n)을 호출하면 빈 스트림이 반환된다.

매핑

MAP

  • 스트림은 파라미터로 제공되는 함수(Function<T, R>관련된 함수형 인터페이스)를 적용해서 기존 요소를 새로운 요소로 매핑시키는 map이라는 메서드를 제공한다.
  • 기존 값을 변경한다는 개념보다는 새로운 값을 만든다는 개념이므로 변환(transforming) 에 매핑(mapping) 이라는 단어를 사용한다.

  • 또한 map은 반환하는 형태에 따라 여러 메서드가 존재한다.

    • mapToIntmapToLongmapToDoublemapToObj가 다음에 해당한다.
    • 일반 스트림과 기본형 특화 스트림은 위의 메서드 중에서 타입에 따라 3가지씩 가지고 있고 없는 메서드는 결국 자기 자신 타입의 스트림을 반환하는 것이기 때문에 map 메서드가 그 역할을 하는 것이다.
    • 예를 들어, IntStream의 경우 mapmapToLongmapToDoublemapToObj가 존재하며 map 자체가 IntStream을 반환하고 Stream의 경우 mapmapToIntmapToLongmapToDouble가 존재하며 map 자체가 Stream을 반환한다.

스트림 평면화(flatMap)

  • 스트림은 파라미터로 제공되는 함수(Function<T, Stream<R>>과 관련된 함수형 인터페이스)를 적용해서 스트림의 각 값을 다른 스트림으로 만든 다음에 모든 스트림을 하나의 스트림으로 연결하는 기능을 수행하는 flatMap이라는 메서드를 제공한다.

  • 추상적으로 설명하면 차원을 낮추는 개념이라고 생각된다. (ex. Stream<String[]> -> Stream<String>)

    • 위의 예시의 경우 일반 map 메서드를 사용할 경우 String[] 배열 자체가 다른 객체로 변환되는데 flatMap을 사용하면 String[] 내부의 값들 자체를 다른 객체로 변환하는 것이 가능하다.
  • 여기서 말하는 함수는 map의 Function<T, R>과 약간의 차이가 있다.

    • flatMap에서 사용되는 Function은 T는 동일하지만 R이 Stream<R>이다.
    • 즉, 일반 제네릭 타입(R)의 객체가 아니라 일반 스트림(Stream<R>)이나 기본형 특화 스트림(IntStreamLongStreamDoubleStream)과 같이 스트림 타입이 반환되어야 한다.

  • 또한 flatMap은 반환하는 형태에 따라 여러 메서드가 존재한다.

    • flatMapToIntflatMapToLongflatMapToDouble이 다음에 해당한다.
    • 일반 스트림에서만 위의 3가지 메서드가 추가로 존재하며 기본형 특화 스트림에서는 flatMap만 존재하고 각각의 타입에 맞는 기본형 특화 스트림을 반환한다.

검색과 매칭

NONEMATCH

  • 프레디케이트가 주어진 스트림에서 일치하는 요소가 없는지 확인

ANYMATCH

  • 프레디케이트가 주어진 스트림에서 적어도 한 요소와 일치하는지 확인

ALLMATCH

  • 프레디케이트가 주어진 스트림에서 모든 요소가 일치하는지 확인

쇼트서킷 평가

때로는 전체 스트림을 처리하지 않았더라도 결과를 반환할 수 있다. 예를 들어 여러 and 연산으로 연결된 커다란 boolean 표현식을 평가한다고 가정하자. 표현식에서 하나라도 거짓이라는 결과가 나오면 나머지 표현식의 결과와 상관없이 전체 결과도 거짓이 된다. 이러한 상황을 쇼트 서킷이라고 부른다. allMatch, anyMatch, noneMatch findFirst, findAny 등의 연산은 모든 스트림의 요소를 처리하지 않고도 결과를 반환할 수 있따. 원하는 요소를 찾았으면 즉시 결과를 반환할 수 있다. 마찬가지로 스트림의 모든 요소를 가진 스트림을 유한한 크기로 줄일 수 있는 유용한 연산이다.

Optional

  • Optioncal 클래스는 값의 존재나 부재 여부를 표현하는 컨테이너 클래스다.
  • isPresent()는 Optional이 값을 포함하면 참(true)을 반환하고, 값을 포함하지 않으면 거짓(false)을 반환한다.
  • ifPresent(Consumer block)은 값이 있으면 주어진 블록을 실행한다.
  • T get()은 값이 존재하면 값을 반환하고, 값이 없으면 NoSuchElementException을 일으킨다.
  • T orElse(T other)는 값이 있으면 값을 반환하고, 값이 없으면 기본값을 반환한다.

리듀싱

: 모든 스트림의 요소를 처리해서 값을 도출한다.

요소의 합

int sum = numbers.stream().reduce(0, (a, b) -> a + b);
  • 위의 reduce는 두 개의 인수를 갖는다.

    • 초깃값 -> 0
    • 두 요소를 조합해서 새로운 값을 만드는 BinaryOperator<T>

초깃값 없음

Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b));
  • 위의 reduce는 BinaryOperator<T>만 인수로 갖는다.
  • Optional로 반환하는 이유는 초깃값이 없어서 아무것도 반환하지 않을 수 있기 때문에 Optional 객체로 감싸서 반환되어진다.

[Stream API] 중간 연산 - slicing 관련 메서드들

[Stream API] 중간 연산 - flatMap 메서드

[Stream API] 중간 연산 - map 메서드

자바의 정석 3판

0개의 댓글

관련 채용 정보