본문 바로가기

- Java

Stream 기본

반응형

1. 스트림이란

- 자바 8 API에 추가된 기능

 

- 선언형으로 컬렉션 데이터 처리

    → 데이터 처리 임시 구현 코드 대신 질의로 표현

 

- 스트림은 데이터 컬렉션 반복을 멋지게 처리하는 기능

 

- 멀티 스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리 가능

 

- 고수준 빌딩 블록: filter, sorted, map, collect 등

    → 특정 스레딩 모델에 제한되지 않고 자유롭게 어떤 상황에서 사용 가능

 

- 데이터 처리 과정을 병렬화하면서 스레드와 락을 고려하지 않을 수 있음

 

- 특징

    1. 선언형: 더 간결하고 가독성 향상

    2. 조립가능: 유연성 향상

    3. 병렬화: 성능 향상

 

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

 

- 스트림 중요 특징

    1. 파이프라이닝(Pipelining)

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

        → 게으름(laziness), 쇼트서킷(short-cricuiting) 같은 최적화 가능

        → 연산 파이프라인은 데이터베이스 질의와 비슷

    2.내부 반복

        → 컬렉션은 반복자를 이용해서 명시적으로 반복하지만, 스트림은 내부 반복을 지원

1
2
3
4
5
6
7
8
9
10
    List<String> threeHighCaloricDishNames =
        Dish.menu.stream() // 메뉴에서 스트림 얻기
            // 파이프라인 연산 만들기
            .filter(dishVo -> dishVo.getCalories() > 300// 고칼로리 요리 필터, Stream<Dish>
            .map(Dish::getName) // 요리명 추출 Stream<String>
            .limit(3// 선착순 3개만 선택 Stream<String>
            .collect(toList()); // 결과를 다른 리스트로 저장 List<String>
 
    System.out.println(threeHighCaloricDishNames);
    // [pork, beef, chicken]

 

2. 스트림과 컬렉션

- 자바의 기존 컬렉션과 새로운 스트림 모두 연속된 요소 형식의 값을 저장하는 자료구조의 인터페이스를 제공

    → 연속된(sequenced): 순차적으로 값에 접근을 의미

 

- 차이점

    데이터를 언제 계산하는 지

    데이터 반복 처리 방법

 

- 스트림

    1. 내부반복

        → 함수에 어떤 작업을 수행할지 지정하면 자동 처리

        → 자동으로 병렬성 구현

    2. 탐색된 스트림의 요소는 소비(일회성)

    3. 게으른 생성(필요할 때만 값 계산)

        → 스트림은 게으른 컬렉션

        → 이론적으로 요청할 때만 요소를 계산

 

- 컬렉션

    1. 외부 반복

        → 컬렉션 인터페이스를 사용하기 위해 for-each 등으로 사용자가 직접 요소를 반복

        → 병렬성을 개발자가 관리(synchronized 등)

    2. 적극적 생성(값이 다 계산될 때까지 대기)

 

3. 스트림 연산

- 중간 연산(intermediate operation)

    → 연결할 수 있는 스트림 연산

    → 중요한 특징은 단말 연산을 스트림 파이프라인에서 실행하기 전까지 수행하지 않음(게으르다)

    → 스트림을 반환하여 서로 연결

 

- 최종 연산(terminal operation)

    → 스트림을 닫는 연산

    → 스트림 파이프라인에서 결과를 도출

    → 연산결과 반환(long, void, List, Map 등)

 

- 예제

    1. limit, short circuit으로 3개 추출

    2. loop fusion: filter와 map은 서로 다른 연산이지만 한 과정으로 병합

1
2
3
4
5
6
7
8
9
    List<String> threeHighCaloricDishNames =
        Dish.menu.stream()
            .filter(dishVo -> dishVo.getCalories() > 300// 중간 연산
            .map(Dish::getName) // 중간 연산
            .limit(3// 중간 연산
            .collect(toList()); // 최종연산
 
    System.out.println(threeHighCaloricDishNames);
    // [pork, beef, chicken]

 

- 스트림 이용하기

    1. 질의를 수행할 컬렉션과 같은 데이터 소스

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

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

 

 

참고: 모던 자바 인 액션
반응형

'- Java' 카테고리의 다른 글

병렬 데이터 처리  (0) 2020.11.08
Stream 기능  (0) 2020.10.24
lambda  (0) 2020.10.18
final / static final  (0) 2020.07.21
Map to Json, Json to Map + ObjectMapper + Gson  (0) 2020.07.17