Hansel
Stream 본문
스트림 API
스트림이란 무엇인가?
자바의 대부분 애플리케이션은 컬렉션을 만들고. 처리하는 과정을 포함한다.
자바에서는 컬렉션으로 데이터를 그룹화하고 처리할 수 있다.
스트림 없는 코드
메뉴들 중에서 칼로리가 400 이하인 메뉴만 골라
해당 메뉴를 다른 컬렉션에 저장하고
칼로리를 기준으로 정렬하는 코드이다.
스트림 사용 코드
스트림을 사용하니 로직이 더 명확하며 명시적이다.
코드가 더 간결한 것은 당연히 보인다.
Stream 대신 parallerStream을 사용하면 멀티코어 아키텍쳐에서 병렬로 실행할 수 있다.
속도측면에서 얼마나 좋은지는 다음에 설명한다.
자바 8의 스트림 API의 특징은 다음과 같다.
- 선언형 : 더 간결하고 가동석이 좋다.
- 조립할 수 있다. : 유연성이 좋아진다.
- 병렬화 : 성능이 좋아진다.
스트림 시작하기
스트림이란 정확히 무엇일까?
스트림은 데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소로 정의할 수 있다.
- 연속된 요소 : 스트림은 특정 요소 형식으로 이루어진 연속된 값 집합의 인터페이스를 제공한다. Filter, sorted, map 처럼 표현 계산식이 주를 이룬다. 스트림의 주제는 계산이다.
- 소스 : 스트림은 데이터 제공 소스로부터 데이터를 소비한다. 정렬된 컬렉션으로 스트림을 생성하면 정렬은 그대로 유지된다.
- 데이터 처리 연산 : 스트림은 함수형 프로그래밍 언어에서 일반적으로 지원하는 연산과 데이터베이스와 비슷한 연산을 지원한다.
중요한 특징 2가지
- 파이프라이닝 : 스트림 연산은 스트림 연산끼리 연결해서 커다란 파이프 라인을 구성할 수 있도록 스트림 자신을 반환한다. 이덕에 Laziness, Short-circuiting 같은 최적화를 얻을 수 있다.
- 내부 반복 : 반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 스트림은 내부 반복을 지원한다.
Map은 뭘까?
Map은 람다를 이용해서 한 요소를 다른 요소로 변환하거나 정보를 추출한다.
스트림과 컬렉션
외부 반복과 내부 반복
컬렉션을 사용하면 사용자는 직접 요소를 반복한다.
-> for-each등을 사용한 방식
반면 스트림은 반복을 알아서 처리하고 결과 스트림을 어딘가에 저장하는 내부 반복을 사용한다.
외부 반복은 명시적으로 컬렉션 항목을 하나씩 가져와서 처리한다.
장난감을 정리해라! 라는 명령을 들었을 때
로봇 하나, 공룡 하나, 자동차 하나 이렇게 처리하는 방식이 바로 외부 반복이다.
명령도 똑같다. 그거 정리하자, 이거 정리하자 하는 식으로 결국 모든 장난감에 대해 각각 명령과 처리가 이루어진다.
한번에 명령을 내리고 처리할 때는 두 손을 사용해 처리하면 더 좋지 않을까?
스트림 라이브러리는 데이터 표현과 하드웨어를 활용한 병렬성 구현을 자동으로 선택한다.
중간연산
Filter , map 등은 서로 연결되어 파이프라인을 형성하고,
Collect로 파이프라인을 실행한 다음에 닫는다.
연결할 수 있는 연산을 중간 연산이라고 하고, 닫는 연산을 최종 연산이라고 한다.
- 중간연산
중간연산은 다른 스트림을 반환한다. 따라서 여러 중간 연산을 연결해 질의를 만들 수 있다.
디버깅을 위해 중간연산 내부에 프린트를 추가했다.
Filter를 살펴보면 모든 데이터를 처리해서 보지 않고 필터 조건에 맞는
데이터만 출력되고 있으며,
필터와 맵은 서로 다른 연산이지만 한 과정으로 병합되어있다.
스트림의 중간 연산은 Lazy evaluation 으로 최종 연산이 호출될 때 이뤄지게 된다. 이 중간 연산에서 쓰이지 않는 데이터 원소는 계산이 쓰이지 않게 된다.
이는 쇼트 서킷과 루프 퓨전의 도움으로 가능하다. (나중에 서술)
그래서 스트림은?
따라서 스트림은 다음과 같이 정의할 수 있다.
- 질의를 수행할 데이터 소스
- 스트림 파이프라인을 구성할 중간 연산 연결
- 스트림 파이프라인을 실행하고 결과를 만들 최종 연산
'Java' 카테고리의 다른 글
Baeldung - Stream (0) | 2023.01.19 |
---|---|
Baeldung - Java (Static) (0) | 2023.01.19 |