스트림(Stream)이란?
스트림(Stream)은 자바8 API에 새로 추가된 기능이다.
스트림을 이용하면 선언형으로 컬렉션 데이터를 처리할 수 있다.
또한 스트림을 이용하면 멀티스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다.
스트림은 소프트웨어 공학적으로 다음의 다양한 이득을 준다.
- 선언형으로 코드를 구현할 수 있다.
- 루프와 if 조건문 등의 제어 블록을 사용해서 어떻게 동작을 구현할지 지정할 필요 없이 '저칼로리의 요리만 선택하라' 같은 동작의 수행을 지정할 수 있다.
- filter, sorted, map, collect 같은 여러 빌딩 블록 연산을 연결해서 복잡한 데이터 처리 파이프라인을 만들 수 있다.
- 여러 연산을 파이프라인으로 연결해도 여전히 가독성과 명확성이 유지된다.
- 고수준 빌딩 블록으로 이루어져 있으므로 특정 스레딩 모델에 제한되지 않고 자유롭게 어떤 상황에서든 사용할 수 있다.
- 결과적으로 우리는 데이터 처리 과정을 병렬화하면서 스레드와 락을 걱정할 필요가 없다.
딱 한 번만 탐색할 수 있다.
반복자(for-each와 같은)와 마찬가지로 스트림도 한 번만 탐색할 수 있다. 즉, 탐색됨 스트림의 요소는 소비된다.
한 번 탐색한 요소를 다시 탐색하려면 초기 데이터 소스에서 새로운 스트림을 만들어야 한다.(그러려면 컬렉션처럼 반복 사용할 수 있는 데이터 소스여야 한다. 만일 데이터 소스가 I/O 채널이라면 소스를 반복 사용할 수 없으므로 새로운 스트림을 만들 수 없다.)
외부 반복과 내부 반복
컬렉션 인터페이스를 사용하려면 사용자가 직접 요소를 반복해야 한다.(예를 들면 for-each 등을 사용해서) 이를 외부 반복(external iteration)이라고 한다.
반면 스트림 라이브러리는 (반복을 알아서 처리하고 결과 스트림값을 어딘가에 저장해주는) 내부 반복(internal iteration)을 사용 한다.
for-each 루프를 이용하는 외부 반복
List<String> names = new ArrayList<>();
for(Dish: menu) {
names.add(dish.getName());
}
스트림 : 내부 반복
List<String> names = menu.stream()
.map(Dish::getName)
.collect(toList());
내부 반복이 외부 반복보다 좋은 이유
- 투명하게 병렬로 처리하고 더 최적화된 다양한 순서로 처리할 수 있다.
- 외부 반복에서는 병렬성을 스스로 관리해야 한다.
스트림 연산
스트림 인터페이스의 연산은 크게 두 가지로 구분할 수 있다.
- 중간 연산 : 여러 중간 연산을 연결해서 질의를 만들 수 있다. 단말 연산을 스트림 파이프라인에 실행하기 전까지는 아무 연산도 수행하지 않는다. 즉, Lazy 하다. 중간 연산을 합친 다음에 합쳐진 중간 연산을 최종 연산으로 한 번에 처리한다.
- 최종 연산 : 스트림 파이프라인에서 결과를 도출한다. 보통 최종 연산에 의해 List, Integer, void 등 스트림 이외의 결과가 반환된다.
다음은 누가 중간 연산이고 누가 최종 연산인지 요약해서 보여준다.
중간 연산
연산 | 형식 | 반환 형식 | 연산의 인수 | 함수 디스크립터 |
filter | 중간 연산 | Stream<T> | Predicate<T> | T -> boolean |
map | 중간 연산 | Stream<T> | Function<T,R> | T -> R |
limit | 중간 연산 | Stream<T> | ||
sorted | 중간 연산 | Stream<T> | Comparator<T> | (T, T) -> int |
distinct | 중간 연산 | Stream<T> |
최종 연산
연산 | 형식 | 반환 형식 | 목적 |
forEach | 최종 연산 | void | 스트림의 각 요소를 소비스하면서 람다를 적용한다. |
count | 최종 연산 | long(generic) | 스트림의 요소 개수를 반환한다. |
collect | 최종 연산 | 스트림을 리듀스해서 리스트, 맵, 정수 형식의 컬렉션을 만든다. |
참고 자료 :
https://ebook-product.kyobobook.co.kr/dig/epd/ebook/E000002942391
'백엔드 > Java' 카테고리의 다른 글
[Java] 전략 패턴(Strategy Pattern) (0) | 2023.05.17 |
---|---|
[Java] 템플릿 메서드 패턴(Template Method Pattern) (0) | 2023.05.17 |
[Java] 람다(Lambda) (0) | 2023.05.09 |
[Java] 동작 파라미터화(Behavior Parameterization) (0) | 2023.05.09 |
[Java] 런타임 데이터 영역 (Runtime Data Area) (0) | 2023.05.05 |