Hansel

Stream 본문

Java

Stream

핑슬 2022. 10. 23. 18:17

스트림 API

 

스트림이란 무엇인가?

 

자바의 대부분 애플리케이션은 컬렉션을 만들고. 처리하는 과정을 포함한다.

자바에서는 컬렉션으로 데이터를 그룹화하고 처리할 수 있다.

 

스트림 없는 코드

 

메뉴들 중에서 칼로리가 400 이하인 메뉴만 골라

해당 메뉴를 다른 컬렉션에 저장하고

칼로리를 기준으로 정렬하는 코드이다.

 

스트림 사용 코드

 

스트림을 사용하니 로직이 더 명확하며 명시적이다.

코드가 더 간결한 것은 당연히 보인다.

 

 

Stream 대신 parallerStream을 사용하면 멀티코어 아키텍쳐에서 병렬로 실행할 수 있다.

속도측면에서 얼마나 좋은지는 다음에 설명한다.

 

자바 8의 스트림 API의 특징은 다음과 같다.
  1. 선언형 : 더 간결하고 가동석이 좋다.
  2. 조립할 수 있다. : 유연성이 좋아진다.
  3. 병렬화 : 성능이 좋아진다.

 

스트림 시작하기 

 

스트림이란 정확히 무엇일까? 

스트림은 데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소로 정의할 수 있다.

 

  • 연속된 요소 : 스트림은 특정 요소 형식으로 이루어진 연속된 값 집합의 인터페이스를 제공한다. Filter, sorted, map 처럼 표현 계산식이 주를 이룬다. 스트림의 주제는 계산이다.
  • 소스 : 스트림은 데이터 제공 소스로부터 데이터를 소비한다. 정렬된 컬렉션으로 스트림을 생성하면 정렬은 그대로 유지된다. 
  • 데이터 처리 연산 : 스트림은 함수형 프로그래밍 언어에서 일반적으로 지원하는 연산과 데이터베이스와 비슷한 연산을 지원한다.

 

중요한 특징 2가지
  1. 파이프라이닝 : 스트림 연산은 스트림 연산끼리 연결해서 커다란 파이프 라인을 구성할 수 있도록 스트림 자신을 반환한다. 이덕에 Laziness, Short-circuiting 같은 최적화를 얻을 수 있다.
  2. 내부 반복 : 반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 스트림은 내부 반복을 지원한다.

 

 

Map은 뭘까?

Map은 람다를 이용해서 한 요소를 다른 요소로 변환하거나 정보를 추출한다. 

 

 

스트림과 컬렉션

 

외부 반복내부 반복

 

컬렉션을 사용하면 사용자는 직접 요소를 반복한다. 

-> for-each등을 사용한 방식

 

반면 스트림은 반복을 알아서 처리하고 결과 스트림을 어딘가에 저장하는 내부 반복을 사용한다. 

 

외부 반복명시적으로 컬렉션 항목을 하나씩 가져와서 처리한다. 

 

장난감을 정리해라! 라는 명령을 들었을 때 

로봇 하나, 공룡 하나, 자동차 하나 이렇게 처리하는 방식이 바로 외부 반복이다.

 

명령도 똑같다. 그거 정리하자, 이거 정리하자 하는 식으로 결국 모든 장난감에 대해 각각 명령과 처리가 이루어진다.

 

한번에 명령을 내리고 처리할 때는 두 손을 사용해 처리하면 더 좋지 않을까?

 

스트림 라이브러리는 데이터 표현과 하드웨어를 활용한 병렬성 구현을 자동으로 선택한다. 

 

 

 중간연산

Filter , map 등은 서로 연결되어 파이프라인을 형성하고,

Collect로 파이프라인을 실행한 다음에 닫는다.

 

연결할 수 있는 연산을 중간 연산이라고 하고, 닫는 연산을 최종 연산이라고 한다. 

 

  1. 중간연산

중간연산은 다른 스트림을 반환한다. 따라서 여러 중간 연산을 연결해 질의를 만들 수 있다.

 

 

디버깅을 위해 중간연산 내부에 프린트를 추가했다.

Filter를 살펴보면 모든 데이터를 처리해서 보지 않고 필터 조건에 맞는 

데이터만 출력되고 있으며, 

필터와 맵은 서로 다른 연산이지만 한 과정으로 병합되어있다.

 

스트림의 중간 연산은 Lazy evaluation 으로 최종 연산이 호출될 때 이뤄지게 된다. 이 중간 연산에서 쓰이지 않는 데이터 원소는 계산이 쓰이지 않게 된다.

 

이는 쇼트 서킷과 루프 퓨전의 도움으로 가능하다. (나중에 서술)

 

 

 

그래서 스트림은?

따라서 스트림은 다음과 같이 정의할 수 있다.

 

  1. 질의를 수행할 데이터 소스
  2. 스트림 파이프라인을 구성할 중간 연산 연결
  3. 스트림 파이프라인을 실행하고 결과를 만들 최종 연산

 

 

 

 

 

'Java' 카테고리의 다른 글

Baeldung - Stream  (0) 2023.01.19
Baeldung - Java (Static)  (0) 2023.01.19