ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [책 정리]Modern Java In Action 4장
    책정리/Modern Java In Action 2020. 5. 18. 00:04

    Modern Java In Action 정리

    Modern Java In Action을 읽고 내용을 정리해본다.

    4장 스트림 소개

    스트림(Stream)

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

    • 자바8에 추가된 기능으로 스트림을 이용하면 선언형으로 코드를 구현하여 컬렉션 데이터를 처리할 수 있다.
      선언형으로 구현한다는 것은 for 루프나 if 조건문 등의 제어 블록을 사용하지 않고 동작을 지정하는 것이다.
      → 실제 구현은 신경쓰지 않고 사용하는 SQL를 생각하자.
    • 스트림에서 제공하는 filter, sorted, map, collect 같은 메서드들은 특정 스레딩 모델에 제한되지 않고 스레드와 락을 걱정할 필요없이 편리하게 데이터 병렬처리를 가능하게 해준다.

    스트림 기본 구현

    • 기본구현에 사용할 Dish 클래스

      class Dish{
        private final String name;
        private final boolean vegetarian;
        private final int calories;
        private final Type type;
      
        public Dish(String name, boolean vegetarian, int calories, Type type) {
            this.name = name;
            this.vegetarian = vegetarian;
            this.calories = calories;
            this.type = type;
        }
      
        public String getName() {
            return name;
        }
      
        public boolean isVegetarian() {
            return vegetarian;
        }
      
        public int getCalories() {
            return calories;
        }
      
        public Type getType() {
            return type;
        }
      
        enum Type {
            MEAT, FISH, OTHER
        }
      }
    • 스트림 구현에 사용할 Dish 컬렉션

      List<Dish> menu = Arrays.asList(
        new Dish("pork", false, 800, Dish.Type.MEAT),
        new Dish("beef", false, 700, Dish.Type.MEAT),
        new Dish("chicken", false, 400, Dish.Type.MEAT),
        new Dish("french fries", true, 530, Dish.Type.OTHER),
        new Dish("salmon", false, 450, Dish.Type.FISH)
      );
    • 스트림 기본구현

      @Test
      public void 스트림_기본구현(){
        List<String> threeHighCaloricDishNames =
            menu.stream() // 컬렉션에서 스트림(Stream<Dish>)을 가져온다.
                .filter(dish -> dish.getCalories() > 300) // 해당 조건의 요소만 추출한다.
                .map(Dish::getName) // 이름(String) 속성을 스트림(Stream<String)으로 가져온다.
                .limit(3) // 3개를 제외하고 truncate한다.
                .collect(Collectors.toList()); // 스트림을 컬렉션(리스트)로 변환한다.
      
        System.out.println(threeHighCaloricDishNames); // [pork, beef, chicken]
      }
    • filter, map 메서드는 인자로 Functional Interface 인스턴스를 받기 때문에 람다표현식이나, 메서드참조로 간결하게 코딩이 가능하다. 또한 메서드들은 실행 결과로 스트림을 리턴하기 때문에 파이프라인 형태가 된다.
      → 빌더 패턴과 유사하다.

    • 서로 연결이 가능한 filter, map, limit는 중간연산이며, collect는 스트림을 닫는 최종연산이다.

    스트림과 컬렉션

    • 컬렉션은 DVD에 저장된 영화에 비유할 수 있다. 모든 데이터(영화 내용 전부)가 메모리(DVD)에 저장되어 있다.
      컬렉션에는 계산된 결과물이 저장되어 있으며, 주 관심사는 특정요소에 접근하여 값을 계산하거나 치환한다.
    • 스트림은 인터넷으로 스트리밍하는 영화에 비유할 수 있다.
      영화 전체를 모두 받는 것이 아니라 미리 몇 프레임만 내려받아 재생이 가능할 수 있다. 스트림은 이론적으로 요청할 때만 요소를 계산하는 고정된 자료구조다.
    • 스트림은 한번만 탐색이 가능하다.
      이미 소비된 스트림을 사용하려 하면 Exception이 발생하므로 다시 생성하여 사용해야 한다.
    • 컬렉션은 데이터를 순회하기 위해서는 루프문을 이용해 명시적으로 반복해야 한다. → 외부반복
    • 스트림은 반복을 알아서 처리(중간값 저장, 최적화, 병렬성 구현 등) 한다. → 내부반복
      @Test
      public void 스트림_내부반복(){
        // forEach 메서드에서 반복되며 명시적으로 루프문이 필요없다.
        menu.stream()
            .forEach(dish -> System.out.println(dish.getName()));
      }

    스트림은 게으른(lazy) 연산을 지원

    • 스트림 처리시 한 요소는 연결된 모든 파이프라인을 타고나서 다음 요소가 처리된다.

      @Test
      public void 스트림_게으른_연산(){
        List<String> threeHighCaloricDishNames =
            menu.stream()
                .filter((dish) -> {
                    System.out.println("filtering :: " + dish.getName());
                    return dish.getCalories() > 300;
                })
                .map((dish) -> {
                    System.out.println("mapping :: " + dish.getName());
                    return dish.getName();
                })
                .limit(3)
                .collect(Collectors.toList());
      
        System.out.println(threeHighCaloricDishNames); // [pork, beef, chicken]
      }
    • 콘솔출력으로 스트림 처리 순서를 보면 한 요소씩 filter → map → limit → collect 파이프라인을 타는것을 볼 수 있다. 중간 연산들(filter → map → limit)을 합친 다음에 최종 연산(collect)에서 한 번에 처리한다.

      filtering :: pork
      mapping :: pork
      filtering :: beef
      mapping :: beef
      filtering :: chicken
      mapping :: chicken
      [pork, beef, chicken]
    반응형

    댓글

Designed by Tistory.