본문 바로가기
Modern java in action

[modern java in action] Stream(1)

by 상국이 2021. 6. 24.
728x90

3-1 스트림이란?

→ 데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소

특징

 - 선언형 : 더 간결하고 가독성이 좋아진다.

 - 조립할 수 있음 : 유연성이 좋아진다.

 - 병렬화 : 성능이 좋아진다.

 

3-2 스트림 시작하기

 - 연속된 요소 : 특정 요소 형식으로 이루어진 연속된 값 집합의 인터페이스

 - 소스 : 컬렉션, 배열, I/O 자원 등의 데이터 제공 소스로부터 데이터를 소비한다 / 정렬된 컬렉션으로 스트림을 생성하면 정렬이 그대로 유지된다.

 - 데이터 처리 연산 : 함수형 프로그래밍 언어에서 지원하는 연산과 데이터베이스와 비슷한 연산을 지원한다. (filter, map, reduce, find, match, sort) / 스트림 연산은 순차적, 또는 병렬로 실행할 수 있다.

스트림 의 중요한 특징

 - 파이프 라이닝 : 대부분의 스트림 연산은 스트림 연산끼리 연결해서 커다란 파이프 라인을 구성할 수 있도록 자신을 반환한다.

 - 내부 반복 : 반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 스트림은 내부 반복을 지원한다.

예시)

스트림 특징

 

import static java.util.stream.Collectors.toList;
 
List<String> threeHighCaloricDishNames =
        menu.stream()                                       //메뉴(요리 리스트)에서 스트림을 얻는다
            .filter(dish -> dish.getCalories() > 300)       //파이프라인 연산 만들기, 고칼로리 요리를 필터링한다.
            .map(Dish::getName)                             //요리명 추출   
            .limit(3)                                       //선착순 3개만
            .collect(toList());                             //결과를 다른 리스트로 저장 / 반환

3-3 스트림과 컬렉션

→ 기존 컬렉션과 새로운 스트림 모두 연속된(순차적으로 값에 접근) 요소 형식의 값을 저장하는 자료구조의 인터페이스를 제공

 

특징

1) 딱 한 번만 탐색할 수 있다.

 → 탐색된 스트림의 요소는 소비되어 다시 탐색하려면 초기 데이터 소스에서 새로운 스트림을 만들어야 한다.

2) 외부 반복과 내부 반복

 → 외부반복 : 명시적으로 컬렉션 항목을 가져와서 처리 (컬렉션)

     내부반복 : 반복을 알아서 처리하고 결과 스트림 값을 어딘강 저장 (스트림)

 * 내부 반복의 장점

    (1) 작업을 투명하게 병렬로 처리하거나 더 최적화된 다양한 순서로 처리할 수 있다.

    (2) 데이터의 표현과 하드웨어를 활용한 병렬성 구현을 자동으로 선택한다.

 

3-4 스트림 연산

 → 중간연산(연결할 수 있는 연산)과 최종 연산(스트림을 닫는 연산)이 있다.

중간연산

 → 단말 연산을 스트림 파이프라인에 실행하기 전까지는 아무 연산도 수행하지 않는다. 

연산형식반환 형식연산의 인수함수 디스크럽터

filter 중간 연산 Stream<T> Predicate<T> T -> boolean
map 중간 연산 Stream<R> Function< T , R > T -> R
limit 중간 연산 Stream<T>    
sorted 중간 연산 Stream<T> Comparator<T> ( T , T ) -> int
distinct 중간 연산 Stream<T>    

최종연산

 → 최종 연산에 의해 List, Integer, void등 스트림 이외의 결과가 반환

연산형식반환형식목적

forEach 최종 연산 void 스트림의 각 요소를 소비하면서 람다를 적용한다.
count 최종 연산 long(generic) 스트림의 요소 개수를 반환한다.
collect 최종 연산   스트림을 리듀스해서 리스트, 맵, 정수 형식의 컬렉션을 만든다.

스트림 이용

 - 질의를 수행할 데이터 소스

 - 스트림 파이프라인을 구성할 중간 연산 연결

 - 스트림 파이프라인을 실행하고 결과를 만들 최종 연산

 

정리

  • 스트림은 소스에서 추출된 연속 요소로, 데이터 처리 연산을 지원한다.
  • 스트림은 내부 반복을 지원한다. 내부 반복은 filter, map, sorted등의 연산으로 반복을 추상화한다.
  • 스트림에는 중간 연산과 최종 연산이 있다.
  • 중간 연산은 filter, map처럼 스트림을 반환하면서 다른 연산과 연결되는 연산이다. 중간 연산을 이용해서 파이프 라인을 구성할 수 있지만 중간 연산으로는 어떤 결과도 생성할 수 없다.
  • forEach나 count처럼 스트림 파이프라인을 처리해서 스트림이 아닌 결과를 반환하는 연산을 최종 연산이라고 한다.

 

연산형식반환 형식사용된 함수형 인터페이스 형식함수 디스크립터작업연산형식반환 형식사용된 함수형 인터페이스 형식함수 디스크립터작업

filter 중간 연산 Stream<T> Predicate<T> T ->  boolean 요소들을 조건에 따라 걸러내는 작업
distinct 중간 연산
(상태가 있는 언바운드 → 내부 상태가 한정되어있지 않음)
Stream<T>     중복을 제거하여 새로운 스트림 리턴
skip 중간 연산
(상태가 있는 바운드)
Stream<T> long   일정 개수만큼 아이템을 건너띄고 나머지 요소들로 스트림을 생성
limit 중간 연산
(상태가 있는 바운드)
Stream<T> long   스트림에서 일정 개수만큼 가져와서 새로운 스트림 리턴
map 중간 연산 Stream<R> Function<T, R> T ->  R 요소들을 특정 조건에 해당하는 값으로 변환
flatMap 중간 연산 Stream<R> Function<T,
Stream<R>>
T -> Stream<R>  스트림의 형태가 배열과 같을 때 모든 원소를 안일 원소 스트림으로 반환
sorted 중간 연산
(상태가 있는 언바운드 → 내부 상태가 한정되어있지 않음)
Stream<T> Comparator<T> (T, T) -> int 요소들을 정렬해주는 작업
anyMatch 최종 연산 boolean Predicate<T> T ->  boolean 최소한 한 개의 요소가 주어진 조건에 만족하는지 검사
noneMatch 최종 연산 boolean Predicate<T> T ->  boolean 모든 요소들이 주어진 조건을 만족하지 않는지 조사
allMatch 최종 연산 boolean Predicate<T> T ->  boolean 모든 요소들이 매개값으로 주어진 조건을 만족하는지 조사
findAny 최종 연산 Optional<T>     스트림의 순서와 관계없이 먼저 찾아지는 객체를 리턴
findFirst 최종 연산 Optional<T>     순서상 가장 첫 번째 있는 것을 리턴
forEach 최종 연산 void Consumer<T> T ->  void 지정된 작업을 스트림의 모든 요소에 대해 수행
collect 최종 연산 R Collector<T, A, R>   미리 작성된 다양한 종류의 컬렉터로 리턴
reduce 최종 연산
(상태 있는 바운드)
Optional<T> BinaryOperator<T> (T, T) -> int 스트림의 요소를 줄여나가면서 연산을 수행하고 최종 결과를 리턴
→ 처음 두 요소를 가지고 연산한결과를 가지고 다음 요소와 연산
count 최종 연산 long     스트림 요소의 개수 리턴

 

728x90

댓글