ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Functional Interface
    Study/Effective Java 2023. 4. 17. 23:32

    함수형 인터페이스

    하나의 추상 메서드를 지정하는 인터페이스.

    (default method 또는 static method 등을 포함하더라도 추상 메서드가 오직 하나면 함수형 인터페이스이다.)

     

    lambda expression 또는 Method reference에 대한 target type을 제공한다.

    public class UsageOfFunctions {
    
        public static void main(String[] args) {
            List<LocalDate> dates = new ArrayList<>();
            dates.add(LocalDate.of(1982, 7, 15));
            dates.add(LocalDate.of(2011, 3, 2));
            dates.add(LocalDate.of(2013, 1, 28));
    
            Predicate<LocalDate> localDatePredicate = d -> d.isBefore(LocalDate.of(2000, 1, 1));
            Function<LocalDate, Integer> getYear = LocalDate::getYear;
            List<Integer> before2000 = dates.stream()
                    .filter(localDatePredicate)
                    .map(getYear)
                    .collect(Collectors.toList());
        }
    }

     

    전체 표현식을 함수형 인터페이스의 인스턴스로 취급할 수 있다.

     

    java에서 제공하는 기본 함수형 인터페이스 (java.util.function package) 를 익혀두자.

    https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

    Function<T, R>

    T : the type of the input to the function.

    R : the type of the result of the function.

    @FunctionalInterface
    public interface Function<T, R> {
    
        R apply(T t);
    
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
    
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
    
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }

     

    Supplier<T>

    T - the type of results supplied by this supplier.

    @FunctionalInterface
    public interface Supplier<T> {
    
        T get();
    }
    

     

    Consumer<T>

    T - the type of the input to the operation.

    @FunctionalInterface
    public interface Consumer<T> {
    
        void accept(T t);
    
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    }
    

     

    Predicate<T>

    T - the type of the input to the predicate.

    @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();
        }
    }
    

     

    @FunctionalInterface

    함수형 인터페이스임을 가리키는 annotation 이다.

    선언되지 않아도 추상 메서드가 한 개라면 함수형 인터페이스로 사용할 수 있다.

    @FunctionalInterface로 인터페이스를 선언했지만 실제로 함수형 인터페이스가 아니라면 컴파일러가 에러(Multiple non-overriding abstract methods found in interface)를 발생시켜주므로, 선언해주는 것이 좋다.

     

     

    댓글

Designed by Tistory.