ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 챕터[4] 스트림
    모던자바인액션 2020. 10. 21. 15:56

    서론

    자바 8에서 추가된 스트림은 무엇인지 컬렉션과 무엇이 다른지 등 스트림의 대해서 설명


    스트림이란?

    Java 8 API에 새로 추가된 기능으로 스트림을 이용하면 선언형(데이터를 처리하는 임시 구현 코드 대신 질의로 표현)으로 컬렉션 데이터를 처리할 수 있다. 또한 멀티스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다.

    특징으로는 선언형(간결 및 가독성 증가), 조립가능(유연성 증가), 병렬화(성능 증가) 가 존재한다.

    (스트림은 계속해서 챕터에 나오므로 순차적으로 배워가면 된다.)


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

    1. 요소의 정의

      • 연속된 요소

        • 컬렉션과 동일하게 스트림은 특정 요소 형식으로 이루어진 연속된 값 집합의 인터페이스를 제공한다. 컬렉션은 자료구조이기에 시간과 공간의 복잡성과 고나련된 요소 저장 및 접근 연산이 주를 이룬다. 반면 스트림은 filter, sorted, map처럼 표현 계산식을 주로 이룬다.

      • 소스

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

      • 데이터 처리 연산

        • 스트림은 함수형 프로그래밍 언어에서 지원하는 연산과 DB와 비슷한 연산을 지원하며, 스트림 연산은 순차적, 병렬로 실행이 가능하다.

    2. 스트림 특징

      • 파이프라이닝

        • 스트림 연산은 스트림 연산끼리 연결해서 커다란 파이프라인을 구성할 수 있도록 스트림 자신을 반환한다. 그 덕분에 게으름(아래에 설명 예정), 쇼트서킷(설명 예정) 같은 최적화도 얻을 수 있으며, 연산 파이프라인은 데이터소스에 적용하는 데이터베이스 질의와 비슷하다.

      • 내부 반복

        • 반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 내부반복을 지원한다.(아래에 설명 예정)

    스트림과 컬렉션 차이

    • 컬렉션

      • 현재 자료구조가 포함하는 모든 값을 메모리에 저장하는 자료구조로 모든 요소는 컬렉션에 추가하기 전에 계산이 되어 있어야한다.(추가 및 삭제의 연산을 수행할 때마다 컬렉션의 모든 요소를 메모리에 저장해야 하며, 컬렉션에 추가하려는 요소는 미리 계산이 되어있어야 한다.)

    • 스트림

      • 스트림은 이론적으로는 요청할 때만 요소를 계산하는 고정된 자료구조이다. 이러한 특성으로 스트림은 사용자가 요청하는 값만 스트림에서 추출하는게 핵심이다. 물론 사용자는 이러한 변화를 알 수 없어 결국에는 생성자, 소비자 관계를 형성한다. 또한 스트림은 게으르게 만들어지는 컬렉션과 같다.(게으름) 사용자가 데이터를 요청할 때만 값을 계산하여 요청 중심제도즉석 제조라고 불리기도 한다.

    스트림의 소비

    스트림 또한 반복자와 마찬가지로 한번만 탐색이 가능하며, 탐색된 스트림의 요소는 소비되어 사용할 수 없으므로 새로운 스트림을 생성해야 한다.

    List<String> titleList = Arrays.asList("java", "title", "8", "action");
    Stream<String> streamExam = titleList.stream();
    // java, title, 8, action 출력
    streamExam.forEach(System.out::println);
    // IllegalStateException 발생
    streamExam.forEach(System.out::println);

    외부 반복 내부 반복

    컬렉션 인터페이스를 사용하려면 사용자가 직접 요소를 반복해야 하는데 이를 외부 반복이라고 한다. 반면 스트림 라이브러리는 반복을 알아서 처리하고 결과 스트림값을 어딘가에 저장해주는 내부 반복을 사용한다.

    하나의 작업이 종료 시 다음 작업을 명시적으로 처리해주어야 하는 외부 반복과 달리 내부 반복은 명시적으로 처리를 지정해주지 않아도 투명하게 병렬로 처리하거나 더 최적화된 다양한 순서로 처리할 수 있다.

     

    더보기

    외부/내부 반복 차이점 예제소피아에게 인형을 정리하라고 말하는 상황

    나 : 소피아, 장남감 좀 정리하렴. 방바닥에 장난감 있지?

    소피아 : 네 공이 있어요.

    나 : 그럼 공을 상자에 담자. 또 어떤 장난감이 있지?

    소피아 : 인형이 있어요.

    나 : 그럼 인형을 상자에 담자. 또 어떤 장난감이 있지?

    소피아 : 책이 있어요.

    나 : 그럼 책을 상자에 담자. 또 어떤 장난감이 있지?

    소피아 : 아무것도 없어요.

    나 : 참 잘했어.

    스트림 연산

    스트림의 연산은 중간 연산, 최종 연산으로 구분지을 수 있다.

    List<String> calExam = menu.stream()
                             .filter(dish -> dish.getCalories() > 150) // 중간 연산
                             .map(Dish::getName)                       // 중간 연산
                             .limit(2)                                 // 중간 연산
                             .collect(Collectors.toList());            // 최종 연신

    중간 연산은 다른 스트림을 반환한다. 따라서 여러 중간 연산을 연결해 질의를 할 수 있으며, 단말 연산을 스트림 파이프라인에 실행하기 전까지 아무 연산을 수행하지 않는다.(게으름)추후 중간 연산을 합친 다음 최종 연산으로 한 번에 처리한다. 이러한 게으름 특성으로 filter, map등 서로 다른 연산을 병합하여 루프 퓨전을 할 수 있다.

    최종 연산은 스트림 파이프라인에서 결과를 도출하며, List, Integer, void 등 스트림 이외에 결과가 반환된다.

    스트림 이용 결론

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

    그나마 git : github.com/hodolee246/ModernJavaStudygithub.com/hodolee246/ModernJavaStudy/blob/master/src/main/java/com/example/modernjava/ch4/StreamExam.java

    '모던자바인액션' 카테고리의 다른 글

    챕터[7] 스트림 병렬화  (0) 2020.10.21
    챕터[6] 스트림 그룹화  (0) 2020.10.21
    챕터[5] 스트림 데이터 수집  (0) 2020.10.21
    챕터[3] 람다  (0) 2020.10.21
    챕터[2] 동작 파라미터화  (0) 2020.10.21

    댓글

Designed by Tistory.