본문 바로가기
JAVA/Java

[Java] 기본 함수형 인터페이스(Functional Interface)

by 민트맛녹차 2022. 9. 13.

Java8에서 미리 정의해 놓은 함수형 인터페이스들을 알아보자. 다음 인터페이스들은 java.util.function에 정의되어있다.

 

Predicate<T>

Predicate<T> 인터페이스 내에는 boolean test(T t) 라는 추상 메서드가 존재한다. boolean test(T t)는 전달된 인자를 판단해 true 또는 false를 반환해야 하는 상황에서 사용한다.

public static int sum(Predicate<Integer> p, List<Integer> lst) {
    int s = 0;
    for(int n : lst) {
    	if(p.test(n))
        	s += n;
    }
    return s;
}

public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 5, 7, 9, 11, 12);
    int s;
    s = sum(n -> n%2 == 0, list);
    System.out.println("짝수 합: " + s);
    
    s = sum(n -> n%2 != 0, list);
    System.out.println("홀수 합: " + s);
}

위의 코드에서 sum 메서드는 Predicate<Integer> p를 인자로 받아 p.test()를 사용한다. 따라서 sum 메서드의 인자 p에는 추상메서드 test()를 구체화 할 람다가 들어가야 한다. 예제 에서는 짝수와 홀수를 판단하는 람다식을 사용했다.

Predicate<T>를 구체화 한 IntPredicate, LongPredicate, DoublePredicate 도 존재한다. 또 두 개의 인자를 받아 참 거짓을 정하는 BiPredicate<T, U> 도 존재한다.

              

 

Supplier<T>

Supplier<T> 인터페이스 내에는 T get() 이라는 추상 메서드가 존재한다. T get() 은 단순히 무엇인가를 반환할 때 사용한다.

public static List<Integer> makeIntList(Supplier<Integer> s, int n) {
    List<Integer> list = new ArrayList<>();
    for(int i = 0; i < n; i++)
        list.add(s.get());
    return list;
}

public static void main(String[] args) {
    Supplier<Integer> spr = () -> {
        Random rand = new Random();
        return rand.nextInt(50);
    };

    List<Integer> list = makeIntList(spr, 5);
    System.out.println(list);

    list = makeIntList(spr, 10);
    System.out.println(list);
}

위의 코드에서는 makeIntList 메서드가 Supplier<Integer> s를 인자로 받아 s.get()을 사용한다. 따라서 makeList 메서드의 인자 s에 get()을 구체화 해 메서드 내에서 활용할 값을 반환하는 람다식이 들어가야한다. 예제에서는 랜덤 값을 반환하는 식을 사용했다.

Supplier<T>를 구체화 한 IntSupplier, LongSupplier, DoubleSupplier, BooleanSupplier 도 존재한다.

 

Consumer<T>

Consumer<T> 인터페이스 내에는 void accept(T t) 라는 추상 메서드가 존재한다. void accept(T t)는 인자를 받아 사용하지만 반환은 하지 않는 상황에서 사용한다.

    public static void main(String[] args) {
        Consumer<String> c = s -> System.out.println(s);
        c.accept("Mint");
    }

위의 코드에서는 람다식을 사용해 Consumer<String> c 인스턴스를 선언했다. c.accept()를 사용하여 c 인스턴스에 구현한 기능을 사용할 수 있다.

Consumer<T>를 구체화 한 IntConsumer, LongConsumer, DoubleConsumer, 매개변수를 추가로 선언한 ObjIntConsumer<T>, ObjLongConsumer<T>, ObjDoubleConsumer<T> 가 존재한다. 또 두개의 인자를 받는 BiConsumer<T, U>도 존재한다.

 

Function<T, R>

Function<T, R> 인터페이스 내에는 R apply(T t) 라는 추상 메서드가 존재한다. R apply(T t) 는 인자를 받아 반환하는 상황에서 사용하며 가장 흔히 사용할 수 있는 인터페이스이다.

public static void main(String[] args) {
    Function<String, Integer> f = s -> s.length();
    System.out.println(f.apply("Robot"));
}

위의 코드에서는 람다식을 사용해 Function<String, Integer> f 인스턴스를 선언했다. f.apply()를 사용하여 f 인스턴스에 구현한 값을 반환할 수 있다.

 

매개변수와 반환형에 따라 Function<T, R>을 구체화한 여러 인터페이스들이 있다. 그중 BiFunction<T, U, R>은 인자 두개를 받아 반환하는 인터페이스이다. 또, 매개변수 자료형과 반환 자료형이 모두 같을 때 UnaryOperator<T>와 BinaryOperator<T>를 사용한다.

 

참조
윤성우의 열혈 JAVA 프로그래밍

댓글