[Java 8] 3. Predicate (Consumer도 같이 써보기)

seony·2023년 4월 23일

java8

목록 보기
3/16

⭐️ Predicate Interface

  • test 추상 메서드를 구현하면 된다.
    • 인자 1개를 받아 boolean을 반환한다.
  • and, or 등을 사용해서 chaining할 수 있다.

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Predicate<T> {


    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }


    default Predicate<T> negate() {
        return (t) -> !test(t);
    }


    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }

    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) {
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    }
}

🌱 Predicate 예시

package com.learnJava.functionalInterfaces;

import java.util.function.Predicate;

public class PredicateExample {

    static Predicate<Integer> p = (i) -> { return i % 2 == 0; };
    // {} 없앤 버전
    static Predicate<Integer> p1 = (i) -> i % 2 == 0;
    static Predicate<Integer> p2 = (i) -> i % 5 == 0;

    // And 메서드 확인
    public static void predicateAnd() {
        System.out.println("Predicate And result is : " + p1.and(p2).test(10)); // predicate chaining
        System.out.println("Predicate And result is : " + p1.and(p2).test(9)); // predicate chaining

    }

    // Or 메서드 확인
    public static void predicateOr() {
        System.out.println("Predicate Or result is : " + p1.or(p2).test(10)); // predicate chaining
        System.out.println("Predicate Or result is : " + p1.or(p2).test(8)); // predicate chaining

    }
    // Negate 메서드 확인
    public static void predicateNegate() {
        System.out.println("Predicate Negate result is : " + p1.or(p2).negate().test(8)); // predicate chaining

    }

    public static void main(String[] args) {

        System.out.println(p.test(4));

        System.out.println(p1.test(4));

        predicateAnd();
        predicateOr();
        predicateNegate();

    }
}

결과

true
true
Predicate And result is : true
Predicate And result is : false
Predicate Or result is : true
Predicate Or result is : true
Predicate Negate result is : false

🌱 Predicate를 사용해서 Student 필터링 해보기

package com.learnJava.functionalInterfaces;

import com.learnJava.data.Student;
import com.learnJava.data.StudentDataBase;

import java.util.List;
import java.util.function.Predicate;

public class PredicateStudentExample {

    static Predicate<Student> p1 = (s) -> s.getGradeLevel() >= 3;
    static Predicate<Student> p2 = (s) -> s.getGpa() >= 3.9;

    // GradeLevel로 필터링
    public static void filterStudentsByGradeLevel() {
        System.out.println("PredicateStudentExample.filterStudentsByGradeLevel");
        List<Student> studentList = StudentDataBase.getAllStudents();

        studentList.forEach(student -> {
            if (p1.test(student)) {
                System.out.println(student);
            }
        });
    }

    // Gpa로 필터링
    public static void filterStudentsByGpa () {
        System.out.println("PredicateStudentExample.filterStudentsByGpa");
        List<Student> studentList = StudentDataBase.getAllStudents();

        studentList.forEach(student -> {
            if (p2.test(student)) {
                System.out.println(student);
            }
        });
    }

    // GradeLevel, GPA 두 가지 조건으로 필터링
    public static void filterStudents() {
        System.out.println("PredicateStudentExample.filterStudents");
        List<Student> studentList = StudentDataBase.getAllStudents();

        studentList.forEach(student -> {
            // 조건에 맞게 and, or, negate로 바꿔 사용 가능
            if (p1.and(p2).test(student)) {
                System.out.println(student);
            }
        });
    }

    public static void main(String[] args) {

        filterStudentsByGradeLevel();
        filterStudentsByGpa();
        filterStudents();
    }
}

결과

PredicateStudentExample.filterStudentsByGradeLevel
Student{name='Emily', gradeLevel=3, gpa=4.0, gender='female', activities=[swimming, gymnastics, aerobics]}
Student{name='Dave', gradeLevel=3, gpa=4.0, gender='male', activities=[swimming, gymnastics, soccer]}
Student{name='Sophia', gradeLevel=4, gpa=3.5, gender='female', activities=[swimming, dancing, football]}
Student{name='James', gradeLevel=4, gpa=3.9, gender='male', activities=[swimming, basketball, baseball, football]}


PredicateStudentExample.filterStudentsByGpa
Student{name='Emily', gradeLevel=3, gpa=4.0, gender='female', activities=[swimming, gymnastics, aerobics]}
Student{name='Dave', gradeLevel=3, gpa=4.0, gender='male', activities=[swimming, gymnastics, soccer]}
Student{name='James', gradeLevel=4, gpa=3.9, gender='male', activities=[swimming, basketball, baseball, football]}


PredicateStudentExample.filterStudents
Student{name='Emily', gradeLevel=3, gpa=4.0, gender='female', activities=[swimming, gymnastics, aerobics]}
Student{name='Dave', gradeLevel=3, gpa=4.0, gender='male', activities=[swimming, gymnastics, soccer]}
Student{name='James', gradeLevel=4, gpa=3.9, gender='male', activities=[swimming, basketball, baseball, football]}

🌱 Predicate랑 Consumer를 조합해서 재사용성 높이기

package com.learnJava.functionalInterfaces;

import com.learnJava.data.Student;
import com.learnJava.data.StudentDataBase;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Predicate;

public class PredicateAndConsumerExample {


    // Predicate 만들기
    Predicate<Student> p1 = (s) -> s.getGradeLevel() >= 3;
    Predicate<Student> p2 = (s) -> s.getGpa() >= 3.9;

    // BiPredicate 만들기
    BiPredicate<Integer, Double> biPredicate = (gradeLevel, gpa) -> gradeLevel >= 3 && gpa >= 3.9;

    // BiConsumer 만들기
    BiConsumer<String, List<String>> studentBiConsumer = (name, activities) -> System.out.println(name + " : " + activities);

    // Predicate와 BiConsumer 동시에 사용하기 (forEach에 사용할 Consumer 만들기)
    Consumer<Student> studentConsumer = (student -> {
        if (p1.and(p2).test(student)) {
            studentBiConsumer.accept(student.getName(), student.getActivities());
        }
    });

    // BiPredicate와 BiConsumer 동시에 사용하기 (forEach에 사용할 Consumer 만들기)
    Consumer<Student> studentConsumer2 = (student) -> {
        if (biPredicate.test(student.getGradeLevel(), student.getGpa())) {
            studentBiConsumer.accept(student.getName(), student.getActivities());
        }
    };

    public void printNameAndActivities(List<Student> students) {
        students.forEach(studentConsumer);
        System.out.println("====================================================");
        students.forEach(studentConsumer2);
    }

    public static void main(String[] args) {
        List<Student> studentList = StudentDataBase.getAllStudents();

        new PredicateAndConsumerExample().printNameAndActivities(studentList);
    }
}

결과

Emily : [swimming, gymnastics, aerobics]
Dave : [swimming, gymnastics, soccer]
James : [swimming, basketball, baseball, football]
====================================================
Emily : [swimming, gymnastics, aerobics]
Dave : [swimming, gymnastics, soccer]
James : [swimming, basketball, baseball, football]

0개의 댓글