chapter04. 스트림(Stream)
chapter4. 스트림(Stream) 소개
4.1 스트림이란 무엇인가?
컴퓨터과학에서 스트림(stream)은 기본적으로
시간의 흐름에 따라 순차적으로 사용할 수 있게 되는 일련의 데이터 요소를 가리킨다.
<자바8 스트림 API의 특징>
- 선언형 : 더 간결하고 가독성이 좋아짐
- 조립할 수 있음 : 유연성이 좋아짐
- 병렬화 : 성능이 좋아짐
4.2 스트림 시작하기
스트림의 정의 : 데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소(Sequence of elements)
- 연결된 요소 : 컬렉션과 마찬가지로 스트림은 특정 요소 형식으로 이루어진 연속된 값 집합의 인터페이스를 제공한다.
- 소스 : 스트림은 컬렉션, 배열, I/O 자원 등의 데이터 제공 소스로부터 데이터를 소비한다.
- 데이터 처리 연산 : 함수형 프로그래밍 언어에서 일반적으로 지원하는 연산과 데이터베이스와 비슷한 연산을 지원한다.
스트림의 특징
- 파이프라이닝(Pipelining) : 스트림 연산끼리 연결해서 커다란 파이프 라인을 구성할 수 있음, 게으름(laziness), 쇼트서킷(short-circuiting)같은 최적화도 얻을 수 있음
- 내부반복 : 반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 스트림은 내부 반복을 지원한다.
4.3 스트림과 컬렉션
공통점
연속된 형식의 값을 저장하는 자료구조의 인터페이스를 제공한다.
차이
애초에 컬렉션은 스트림의 재료 중 하나이다.
- 계산 시기
가장 큰 차이는 언제 계산을 하느냐이다. 컬렉션은 모든 값을 메모리에 저장해놔야 하기 때문에 계산이 되어있다. 그래서 이론적으로 아주 큰 컬렉션은 만들 수 없지만, 스트림은 가능하다 (중간에 filter 등으로 요소가 추려진다는 가정하에).
- 소모 및 변경
스트림은 데이터를 저장하지 않아서 변경 불가능하다 (스트림에 데이터를 추가하거나 빼는 것)
또한 스트림은 소모성이여서 사용 후 재사용이 불가능하다.
- 외부 반복과 내부 반복
컬렉션은 사용자가 직접 반복문을 돌리는 외부 반복이다. 스트림은 내부 반복을 사용한다. 선언형과 명령형의 차이인데 이 차이로 인해 가독성이 좋아지고, 병렬성을 얻기도 한다.
물론 내부 반복은 구현이 숨겨져있는 것일 뿐이다.
4.4 스트림 연산
스트림을 통해 배열, 컬렉션 등의 데이터들을 가공할 수 있다.
이때 스트림은 생성, 중간 연산, 최종 연산 순으로 진행되는데, 최종 연산이 없으면 아무 결과도 얻지 못한다.
스트림 인터페이스는 연산을 두 가지로 구분할 수 있다.
- 중간 연산 : 연결할 수 있는 스트림 연산
- 최종 연산 : 스트림을 닫는 연산이다.
중간 연산을 여러개 연결해서 질의를 만들 수 있는데, 이때 중요한 특징은 단말 연산을 스트림 파이프라인에 실행하기 전까지는 아무 연산도 수행하지 않는다는 것
즉, 중간 연산을 호출하는 것은 단지 어떤 작업이 수행되어야 하는지를 지정해주는 것
중간 연산을 합친 다음에 합쳐진 중간 연산을 최종 연산으로 한 번에 처리 - 이를 게으르다고 표현함
중간 연산은 조건에 맞는 요소를 추출(filter()) 하거나 요소를 변환(map()) 한다.
예를 들어, 문자열 길이가 5보다 작은 것들로 filter하거나 플레이어 객체에서 플레이어의 이름만 가져오기
filter와 map은 서로 다른 연산이지만 한 과정으로 병합된다 → 루프 퓨전
최종 연산은 스트림 파이프라인에서 결과를 도출한다. 최종 연산에 의해 반환되는 결과는 List, Integer, void 등 스트림이 아닌 결과를 반환한다.
주의 - 스트림은 한 번만 소비될 수 있기 때문에 최종 연산이에 스트림은 더 이상 다른 연산을 적용할 수 없다.
예시: forEach(),count(), sum(), reduce(), collect() 등이 있다