Chapter 6 - 스트림으로 데이터 수집

2022. 9. 25. 16:32개발 관련 책 읽기/모던 자바 인 액션

✅ 아래 내용들에 대해서 알아보자

- Collectors 클래스로 컬렉션을 만들고 사용하기
- 하나의 값으로 데이터 스트림 리듀스하기
- 특별한 리듀싱 요약 연산
- 데이터 그룹화와 분할
- 자신만의 커스텀 컬렉션 개발

 

모든 실습 내용은 깃허브(아래 링크)에 있습니다. 참고 부탁드립니다 😀😀

https://github.com/underdarks/ModernJavaInAction-TIL/tree/main/src/test/java/modernjavainaction/practice

 


 

컬렉터란 무엇인가?

컬렉터(Collector) 인터페이스 구현은 스트림의 요소를 어떤 식으로 도출할지 지정한다.

예를들어, toList()를 사용하면 각 요소를 리스트로 만들어라는 의미로 사용가능하다.

collect를 호출하면 컬렉터가 스트림의  요소에 reducing 연산을 수행하여 데이터 구조를 도출할 수 있다.

 

자 그러면 간단한 예시 코드를 보면서 이해해보자.

짝수를 필터링하여 collect(toList()) 를 사용하여 List<Integer>로 변환하는 코드를 볼 수 있다.

@DisplayName("고유 요소로 이루어진 스트림 짝수 필터링")
@Test
public void filterEvenNumber() {
    //given
    List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);

    //when
    List<Integer> evenNumbers = numbers.stream()
            .filter(num -> num % 2 == 0)
            .distinct()         //중복 제거
            .collect(toList());

    //중복 제거 된 짝수 출력
    evenNumbers.stream()
            .forEach(System.out::println);

    //then
    assertThat(evenNumbers.size()).isEqualTo(2);
}

 

Collectors에서 제공하는 메서드의 기능은 크게 3가지로 구분된다.

- 스트림 요소를 하나의 값으로 리듀싱 및 요약

- 요소 그룹화

- 요소 분할

 

하나하나씩 알아보자.

 


리듀싱

 

counting을 활용하여 음식들의 개수를 계산하는 하는 코드이다.

   /**
     * 6.2.0 - 요리 개수 구하기 (202p)
     */
    @DisplayName("counting() 활용한 요리 계수 구하기")
    @Test
    public void getFoodCount() {
        //given
//        Long collect = menu.stream().count();

        Long foodCount = menu.stream()
                .collect(Collectors.counting());

        //when
        System.out.println("foodCount = " + foodCount);


        //then
        assertThat(foodCount).isEqualTo(9);
    }

 

 

 

가장 칼로리가 높은 음식을 찾는 예시 코드를 보자

collect와 Collectors.maxBy, minBy를 사용하여 칼로리가 가장 높은/낮은 음식을 찾을 수 있다.

/**
 * 6.2.1 - 스트림값에서 최대값 최소값 검색 (202p)
 */
@DisplayName("가장 칼로리가 높은 요리 찾기")
@Test
public void findHighestCalFoodWithComparingInt() {
    //given
    /**
     * 스트림 요소를 비교하는 데 Compareator.comparingint를 사용하고 파라미터로 Dish의 칼로리로 비교한다
     * 그 후 maxBy를 사용하여 파라미터로 Compertator를 넘긴 후 maxBy는 Reducing 사용하여 최대값을 구한다
     */
    Dish dish = menu.stream()
            .collect(Collectors.maxBy(Comparator.comparingInt(Dish::getCalories)))
            .orElse(null);

    //when
    System.out.println("dish = " + dish);


    //then
    assertThat(dish).isNotNull();
}

 


요약 연산

 

Collectors 클래스는 summingInt라는 특별한 요약 팩토리 메서드를 제공한다.

summinInt는 객체 -> int로 매핑하는 함수를 인수로 받아 객체를 int로 매핑한 컬렉터를 반환한다.

 

아래는 summinInt를 활용한 음식들의 총 칼로리를 구하는 예시이다.

   /**
     * 6.2.2 - 요약 연산 (203p)
     */
    @DisplayName("요약 연산을 할용한 음식 총 칼로리 구하기")
    @Test
    public void findTotalCalWithSummarization() {
        /**
         * 1. summingInt는 객체를 int로 매핑하는 함수를 인수로 받는다.
         * 2. 인수로 전달 된 함수는 객체를 int로 매핑한 컬렉터를 반환한다.
         * 3. 그 후 summingInt가 collect메서드로 전달되면 합계 작업을 수행한다.
         */
        //given
        Integer totalCalories = menu.stream()
                .collect(summingInt(Dish::getCalories));

//        int sum = menu.stream()
//                .mapToInt(Dish::getCalories)
//                .sum();
        //when
        System.out.println("totalCalories = " + totalCalories);

        //then
    }

 

 

반응형