모던 자바를 읽고

함수형 인터페이스

쥐4 2024. 11. 14. 12:23

1. Predicate

- Boolean을 반환하는 함수형 인터페이스

- stream의 filter에 유용하게 쓸 수 있다.

        List<Person> people = new ArrayList<>();

        people.add(Person.of("정지호", 4));
        people.add(Person.of("위석현", 4));
        people.add(Person.of("정지섭", 3));
        people.add(Person.of("송민규", 1));
        people.add(Person.of("장진혁", 5));
        people.add(Person.of("기미중", 2));

        List<Person> overTwoGrade = people.stream()
                .filter(person -> person.isHigher(2))
                .toList();

        overTwoGrade.forEach(person -> System.out.println(person.getName()));

<filter안의 람다식은 Predicate 함수형 인터페이스이다. - filter는 true여야 그 뒤의 로직을 실행>

 

2. Consumer

- void를 반환하는 함수형 인터페이스

- forEach에 유용하게 쓸 수 있다.

- peek에 유용하게 쓸 수 있다.(peek vs forEach 이후 stream을 다루며 집중해서 블로그 정리 예정)

        List<Person> people = new ArrayList<>();

        people.add(Person.of("정지호", 4));
        people.add(Person.of("위석현", 4));
        people.add(Person.of("정지섭", 3));
        people.add(Person.of("송민규", 1));
        people.add(Person.of("장진혁", 5));
        people.add(Person.of("기미중", 2));

        List<Person> overTwoGrade = new ArrayList<>();
        
        people.stream()
                .filter(person -> person.isHigher(2))
                .forEach(overTwoGrade::add);

        overTwoGrade.forEach(person -> System.out.println(person.getName()));

 

 

3. Function

- T를 받아 R을 반환하는 함수형 인터페이스

- map에 유용하게 쓸 수 있다.

        List<Person> people = new ArrayList<>();

        people.add(Person.of("정지호", 4));
        people.add(Person.of("위석현", 4));
        people.add(Person.of("정지섭", 3));
        people.add(Person.of("송민규", 1));
        people.add(Person.of("장진혁", 5));
        people.add(Person.of("기미중", 2));

        List<Person> updatedPerson = people.stream()
                .map(person -> {
                    if(person.isName("송민규")){
                        return person.downGrade();
                    }
                    return person.upGrade();
                }).toList();

        updatedPerson.forEach(person -> System.out.println(person.getName() + " " + person.getGrade()));

 

4. Supplier

- 입력값을 받지 않고, 메서드 실행

- 메서드를 저장한다고 보면 된다.

        List<Person> people = new ArrayList<>();

        people.add(Person.of("정지호", 4));
        people.add(Person.of("위석현", 4));
        people.add(Person.of("정지섭", 3));
        people.add(Person.of("송민규", 1));
        people.add(Person.of("장진혁", 5));
        people.add(Person.of("기미중", 2));

        // Supplier에 스트림 파이프라인 로직을 담기
        Supplier<List<Person>> updatedPersonSupplier = () -> people.stream()
                .map(person -> {
                    if(person.isName("송민규")){
                        return person.downGrade();
                    }
                    return person.upGrade();
                }).toList();

        // Supplier의 get() 메서드를 호출하여 결과 리스트 생성
        List<Person> updatedPerson = updatedPersonSupplier.get();

        // 결과 출력
        updatedPerson.forEach(person -> System.out.println(person.getName() + " " + person.getGrade()));
    }

 

 

5. Comparator

- 2개의 입력값을 받아, 정렬을 위해 비교하는 함수형 인터페이스

- 음수일 시 1번을 뒤로, 2번을 앞으로 양수일시, 1번을 앞으로 2번을 뒤로 정렬

        List<Person> people = new ArrayList<>();

        people.add(Person.of("정지호", 4));
        people.add(Person.of("위석현", 4));
        people.add(Person.of("정지섭", 3));
        people.add(Person.of("송민규", 1));
        people.add(Person.of("장진혁", 5));
        people.add(Person.of("기미중", 2));

        // Stream과 Comparator를 사용하여 grade 기준으로 오름차순 정렬
        List<Person> sortedPerson = people.stream()
                .sorted((person1, person2) -> person2.getGrade() - person1.getGrade()) // grade 기준 내림차순 정렬
                .toList();
        
        sortedPerson.forEach(person -> System.out.println(person.getName() + " " + person.getGrade()));