[20210603] Variety Of Stream In Java

숫자형 스트림

기존의 스트림으로 정수로 구성된 스트림의 합을 구한다고 한다면 reduce를 이용하게 된다. 이때, Integer를 기본형(int)으로 언박싱하는 비용이 숨겨져 있다. 이때를 대비해서 숫자 스트림을 효율적으로 처리할 수 있도록 하는 기본형 특화 스트림을 제공한다.

기본형 특화 스트림

자바 8에서는 세 가지 기본형 특화 스트림을 제공한다. 스트림 API는 박싱 비용을 피할 수 있도록 IntStream, DoubleStream, LongStream을 제공한다. 각각의 인터페이스는 sum, max 같이 자주 사용하는 숫자 관련 리듀싱 연상 수행 메서드를 제공한다. 또한 필요시 다시 객체 스트림으로 복원하는 기능도 제공한다.

숫자 스트림으로 매핑

스트림을 특화 스트림으로 변환할 때는 mapToInt, mapToDouble, mapToLong 세 가지 메서드를 가장 많이 사용한다.

객체 스트림으로 복원

특화 스트림을 일반 스트림으로 변환하기 위해서는 boxed 메서드를 이용한다.
혹은, mapToObj를 이용해서 일반 스트림으로 변환 가능하다.

기본값 : OptionalInt

int 기본형은 기본값이 0이기 때문에 잘못된 겨로가가 도출될 수 있다. ex) 최댓값을 찾을 때 스트림에 값이 없으면, 0이 기본값이기에 0이 최대값이 될 수도 있다.
이를 구별하기 위해 OptionalInt, OptionalDouble, OptionalLong 세 가지 기본형 특화 스트림 버전을 제공한다.

숫자 범위

프로그램에서는 특정 범위의 숫자를 이용해야 하는 상황이 자주 발생한다. 자바 8의 IntStream과 LongStream에서는 range와 rangeClosed라는 두 가지 정적 메서드를 제공한다.
두 메서드 모두 첫 번째 인수로 시작값을, 두 번째 인수로 종료값을 갖는다.

  • range - 시작값과 종료값이 결과에 포함되지 않는다.
  • rangeClosed - 시작값과 종료값이 결과에 포함된다.

스트림 만들기

값으로 스트림 만들기

임의의 수를 인수로 받는 정적 메서드 Stream.of를 이용한다.

배열로 스트림 만들기

배열을 인수로 받는 정적 메서드 Arrays.stream을 이용한다.

파일로 스트림 만들기

파일을 처리하는 등의 I/O 연산에 사용하는 자바의 NIO API(비블록 I/O)도 스트림 API를 활용할 수 있도록 업데이트되었다. java.nio.file.Files의 많은 정적 메서드가 스트림을 반환한다.

함수로 무한 스트림 만들기

스트림 API는 함수에서 스트림을 만들 수 있는 두 개의 정적 메서드 Stream.iterate와 Stream.generate를 제공한다. 두 연산을 이용해서 무한 스트림을 만들 수 있다.
iterate와 generate에서 만든 스트림은 요청할 때마다 주어진 함수를 이용해서 값을 만든다.
하지만 보통 무한한 값을 출력하지 않도록 limit(n)함수를 함께 연결해서 사용한다.

iterate 메서드는 초깃값과 람다를 인수로 받아서 새로운 값을 끊임없이 생산할 수 있다.

generate 메서드는 iterate와 달리 생산된 각 값을 연속적으로 계산하지 않는다. generate는 Supplier<T>를 인수로 받아서 새로운 값을 생산한다. 여기서 Supplier 인스턴스는 객체의 상태를 변화시키지 않는 불변 상태를 유지해야 한다. 그렇지 않으면 병렬로 처리하면서 올바른 결과를 얻지 못한다.


출처

Java 8 in Action by Alan Mycroft and Mario Fusco 참고