[JAVA (10)] Stream - Filter, Sort, Map (Day 44)

코딩기록·2024년 12월 10일

[ Stream ]

1. 📜 사용처

  • 배열, List, Map, Set에서 모두 사용 가능하며

2. 🔍 용도

  • Filter , Map, Sort, findFirst, anyMatch, allMatch 등을 사용가능하게 해 주는 클래스


[ Stream().map() ]

1. 📜 구조 설명

  • stream() : filter, map 등의 기능을 사용하기 위해 stream 객체를 만들고
  • .map() : stream 객체의 메소드인 map()을 활용

2. 🔍 사용 용도

  • 데이터를 변환하거나(names.stream().map(String::toUpperCase)
  • 객체의 속성을 추출할 때 사용

3. 📚 예시


        // ========= 요리의 이름들만 추출해서 매핑  ========

        // 1. 정석
        // 요리에 이름만 추출하고 싶다.
        //  1) Map()을 사용하기 위해, Map 메소드를 내장하는 stream 객체로 변환해준다.
        List<String> menuFinal = menuList.stream()
                // 2) map() 메소드를 오버라이딩 해준다. 이 때, 매개변수는 Function 클래스이다.
                .map(new Function<Dish, String>() {
                    @Override
                    public String apply(Dish dish) {
                        return dish.getName();
                    }
                    // 3) .collect(Collectors.toList()) 로 List로 변환해준다. (안할 시 주소만 출력됨)
                }).collect(Collectors.toList());

        // 2. 람다식으로 변경
        List<String> dishNameList = menuList.stream()
                .map((menu) -> menu.getName())
                .collect(toList());
// ======== 요리 중에 요리이름과 칼로리만 추출해서 새로운 객체로 포장하여 배열에 담고싶음 ===== //
        // 1. 익명 클래스 버전
        List<DishDetail> collect = menuList.stream()
                .map(new Function<Dish, DishDetail>() {
                    @Override
                    public DishDetail apply(Dish dish) {
                        // dish.getCalories()와 dish.name()을 추출해야 되는데, 두 개를 한 번에 추출 불가
                        //  => 따라서, 두 정보를 담은 객체를 만들어서, 그 객체를 반환하도록 한다.
                        return new DishDetail(dish);
                    }
                })
                .collect(toList()); // 이걸 System.out.println()을 하면, 각 데이터 요소의 경우 toString()이 자동 적용된다.
        System.out.println(collect);


        // 2. 람다식 표헌
        List<SimpleDish> simpleDishes = menuList.stream()
                .map(menu -> new SimpleDish(menu))
                .collect(toList());

        simpleDishes.forEach(System.out::println);

- 4. ➕ mapToInt()과 함께 쓸 수 있는 sum(), average().getAsDouble()



[ Stream().Filter() ]

1. 📜 구조 설명

  • stream().filter().collect(Collectors.comparing())

  • 자세한 원리는 아래 예시 주석 참고

    
           // 1. 정석버전(원리 설명용)
           menuList.stream() // 1) filter, map 등의 기능을 사용하기 위해 stream 객체를 만들고
                   // 2) stream 객체의 메소드인 map()을 활용. 이 때, 매개변수로는 Predicate  객체를 받음
                   // (상세설명1) 이 때, 사용자가 predicate 객체를 새로 생성하면서 test 함수를 오버라이딩 하면
                   .filter(new Predicate<Dish>() {
                       @Override
                       public boolean test(Dish dish) {
                           return dish.getCalories() > 300;
                       }
                   }) // (상세설명2) filter() 함수의 내부 작동 원리에 따라, stream으로 만든 collection의 각 데이터 요소를 받아서
                     //            위에서 오버라이딩한 test() 메서드에 argument로 전달
                   //              그렇게 해서 return 된 값을 바탕으로 내부 구현 원리에 따라 필터링 된 값만 반환함
                   .limit(3)
                   .collect(toList());
    
           // 2. 람다버전
           List<Dish> limit3 = menuList.stream()
                   .filter(m -> m.getCalories() > 300)
                   .limit(3) // 앞에서부터 3개 선택
                   .collect(toList());

### 2. ➕ 같이 쓸 수 있는 stream 내장 메서드 : skip, limit
   
   <br><br>
## [ ArrayList의 정렬 : Sort ]
### - 1. 기본구조 
   - List에 쓰는 것이다.** 예를 들어 List에 필터링을 한 후 sort를 하고 싶을 때는,필터링을 하기 위해서 stream 객체로 바꾼 후 filtering 진행 하므로, 이 때는 sort 못 쓰고 sorted를 써야 한다.**
   - `List.sort(Comparator.comparing())`
    - 원리 : 1) sort안에 Comparator 객체를 새로 생성하고
            2) 기존 Comparator 객체의 comparing 메서드를 내가 원하는 정렬 기준으로 override해준다.
   ```java
           studentList.sort(new Comparator<Student>() {
            // sort 함수의 내부 구현 코드에 의해서, 1) studentLilst를 순회하면서 배열을 순서대로 돌면서 Student 객체를 가져와서
            @Override
            // 2) if (compare() > 0) 이면 정렬 순서를 바꾼다.
            public int compare(Student o1, Student o2) {
                return  o1.getAge() - o2.getAge();
            }
        });
        
      ```


### - 2. 람다식 식 람다식 함축표현
```java

        // 2. 람다식 : .sort(Comparator.comparing(parameter))
        //       => comparing안에 parameter로 객체를 만들어 준 후, 기존의 메소드를 오버라이딩 해준다.
        studentList.sort(Comparator.comparing((student) -> student.getAge()));

        // 4. 위 식을 ::로 표현
        studentList.sort(Comparator.comparing(Student::getAge));	




[ Colleciton 및 배열의 정렬 : Sorted ]

1. 📜 구조 설명

Collection.stream().sorted(Comparator.comparing(Comparator 객체)).reversed().collect(Collectors.toList());

// 메뉴들을 이름 내림차로 정렬 (zyx순)
       menuList.stream() // 1) sorted를 사용하기 위해서는 먼저 sorted 메서드를 내장하고 있는 stream 객체로 변환해줘야 한다.
               // 2) sorted(Comparator.comparing(Comparator c)로 정렬
               //    - 작동원리 : sorted 함수 내부 작동원리에 의하여,  
               //               1) menuList의 각 데이터 요소를 가져와서
               //               2) 사용자가 오버라이딩한 Comparator.comparing() 메소드를 호출한 후
               //               3) return 값을 활용하여  정렬한다.
               .sorted(Comparator.comparing((Dish dish) -> dish.getName()).reversed()) 
               .collect(toList())
               .forEach(System.out::println);




[ 기타 Stream 내장 메소드]

1. anyMatch(), allMatch()

2. findFirst()

  // anyMatch()
        // 요리 중 채식주의자가 먹을 수 있는 요리가 하나라도 있는지 여부
        boolean flag1 = menuList.stream()
//                .filter(d -> d.getType() == DishType.MEAT)
                .anyMatch(d -> d.isVegetarian());

        // allmATCH()
        System.out.println("flag1 = " + flag1);
        // 요리 중 모든 요리가 1000칼로리 미만입니까?
        boolean flag2 = menuList.stream()
                .allMatch(m -> m.getCalories() < 1000);
        System.out.println("flag2 = " + flag2);

        // 요리 중에 첫번째 발견된 생선 요리를 찾기
        Optional<Dish> firstFish = menuList.stream()
                .filter(m -> m.getType() == DishType.FISH)
                .findFirst();

        
        firstFish.ifPresent(fish -> System.out.println(fish.getName()));

0개의 댓글