상세 컨텐츠

본문 제목

함수형 인터페이스 (Operator, Predicate), andThen(), compose()

기록 - 프로그래밍/Java

by wjjun 2024. 2. 6. 01:07

본문

Operator 인터페이스

Funtion과 동일하게 매개 변수와 리턴값이 있는 applyXXX() 메서드를 갖고 있습니다. 이 메서드는 매개값을 맅너값으로 매핑하는 역할보다는 매개값을 이용해 연산을 수행하고 동일한 타입으로 리턴값을 제공하는 역할입니다.

인터페이스 추상메서드 설명
BinaryOperator<T> BiFunctiom<T,U,R> 하위 인터페이스 T와 U를 연산한 후 R 리턴
UnaryOperator<T> Function<T,T> 하위 인터페이스 T를 연산한 후 T 리턴
DoubleBinaryOperator double applyAsDouble(double, double) 두 개의 double 연산
DoubleUnaryOperator double applyAsDouble(double) 한 개의 double 연산
IntBinaryOperator int applyAsInt(int, int) 두 개의 int 연산
IntUnaryOperator int ApplyAsInt(int) 한 개의 int 연산
LongBinaryOperator long applyAsLong(long,long) 두 개의 long 연산
LongUnaryOperator long applyAsLong(long) 한 개의 long 연산

IntBinaryOperator 인터페이스를 타겟 타입으로 하는 람다식은 applyAsInt() 메서드는 매개값으로 두 개의 int를 가지므로 람다식도 두 개의 int 매개변수 a와 b를 사용한다. 그리고 applyAsInt() 메서드의 리턴 타입이 int 이므로 람다식 중괄호 {}의 리턴값은 int 가 됩니다.

IntBinaryOperator operator = (a, b) -> { ..; return int값; }

 

maxOrMin() 메서드 호출 시 람다식

public class OperatorExample {
    private static int[] socres = { 92, 95, 87 };
    
    public static int maxOrMin(IntBinaryOperator operator) {
        int result = scores[0];
        for (int score : scores) {
            result = operator.applyAsInt(result, score);
        }
        return result;
    }
    
    public static void main(String[] args) {
        int max = maxOrMin(
            (a, b) -> {
                if (a >= b) return a;
                else return b;
            }
        );
        
        sout("최대값 : " + max);
        
        int min = maxOrMin(
            (a, b) -> {
                if (a <= b) return a;
                else return b;
            }
        );
        sout("최소값 : " + min);
    }
}

 

 

Predicate 인터페이스

Predicate 함수적 인터페이스는 매개 변수와 boolean 리턴값이 있는 testXXX() 메서드를 가지고 있습니다. 이 메서드는 매개값을 조사해서 true 또는 false를 리턴하는 역할입니다.

인터페이스 추상메서드 설명
Predicate<T> boolean test(T t) 객체 T를 조사
BiPredicate<T, U> boolean test(T t, U u) 객체 T와 U를 비교 조사
DoublePredicate boolean test(double value) double 값을 조사
IntPredicate boolean test(int value) int 값을 조사
LongPredicate boolean test(long value) long 값을 조사
Predicate<Student> predicate = t -> { return t.getSex().eqauls("남자"); }
Predicate<Student> predicate = t -> t.getSex().eqauls("남자");

 

public static double avg ( Predicate<Student> predicate ) {
    int count = 0;, sum = 0;
    for (Student student : list) {
        if (predicate.test(student) {
            count++;
            sum += student.getScore();
        }
    }
    return (double) sum / count;
}

public static void main(String[] args) {
    double maleAvg = avg( t -> t.getSex().equals("남자"));
    sout("남자 평균 점수 = " + maleAvg);
    double femaleAvg = avg( t-> t.getSex().eqauls("여자"));
    sout("여자 평균 점수 = " + femailAvg);
}

public class Student {
    private String name;
    private Stirng sex;
    private int score;
    
    public Student(String name, String sex, int score) {
        this.name = name;
        this.sex = sex;
        this.score = score;
    }
    
    public String getSex() { return sex; }
    public int getScore() { return score; }
}

 

andThen()과 compose() 디폴트 메서드

디폴트와 정적 메서드는 추상 메서드가 아니기 때문에 추상적 함수적 인터페이스에 선언되어도 여전히 함수적 인터페이스 성질을 잃지 않습니다. 함수적 인터페이스 성질은 하나의 추상 메서드를 갖고 있고 람다식으로 익명 구현 객체를 생성할 수 있는 것을 의미합니다.

 

Consumer, Function, Operator 종류의 함수형 인터페이스는 andThen()과 compose() 디폴트 메서드를 갖고 있습니다. andThen()과 compose() 디폴트 메서드는 두 개의 함수적 인터페이스를 순차적으로 연결하고 첫 번째 처리 결과를 두 번째 매개값으로 제공해 최종 결과 값을 사용합니다.

 

인터페이스 A, B = 인터페이스A.andThen(인터페이스B);

최종결과 = 인터페이스AB.method();

 

Consumer 순차적 연결

andThen() 디폴트 메서드는 함수형 인터페이스의 호출 순서만 결정합니다.

public static void main(String[] args) {
    Consumer<Member> conA = (m) -> {
        sout("conA : " + m.getName());
    };
    
    Consumer<Member> conB = (m) -> {
        sout("conB : " + m.getName());
    };
    
    Consumer<Member> consumerAB = consumerA.andThen(consumerB);
    consumerAB.accept(new Member("홍길동", "hong", null));
 }

 

 

Function 순차적 연결

functionA = (m) -> m.getAddress();
functionB = (a) -> a.getCity();

functionAB = functionA.andThen(functionB);
city = functionAB.apply(new Member("홍", "hong", new Address("한국", "서울")));

functionAB = functionB.compose(functionA);
city = functionAB.apply(new Member("홍", "hong", new Address("한국", "서울")));

andThen() 메서드를 호출한 함수적 인터페이스는 functionA이고, compose() 메서드를 호출한 함수적 인터페이스는 functionB이다. 모두 functionA 부터 실행하고 functionB를 나중에 실행합니다.

 

 

and(), or(), negate() 디폴트 메서드와 isEqual() 정적 메서드

and()는 &&, or()은 ||, negate()는 부정 !

and()메서드는 두 Predicate가 모두 true를 리턴하면 최종적으로 true를 리턴하는 Predicate를 생성합니다. or()는 Predicate 중 하나만 true를 리턴해도 최종적으로 true를 리턴합니다. negate()는 Predicate 결과가 true이면 false를, false이면 true를 리턴하는 새로운 Predicate를 생성합니다. 

 

 

minBy(), maxBy() 정적 메서드

o1, o2를 비교해서 o1이 작으면 음수를, o1과 o2가 동일하면 0을, o1이 크면 양수를 리턴하는 compare() 메서드가 선언되어 있습니다.

리턴타입 정적 메서드
BinaryOperator<T> minBy(Comparator<? super T> comparator)
BinaryOperator<T> maxBy(Comparator<? super T> comparator)
@FunctionalInterface
public interface Comparator<T> {
    public int compare(T o1, T o2);
}

(o1, o2) -> { ...; return int값; }

관련글 더보기

댓글 영역