velog에서 이전한 글 입니다.

람다식

@FunctionalInterface
interface MyFunction {
    void run();  // public abstract void run();
}

class Main {
    static void execute(MyFunction f) { // 매개변수의 타입이 MyFunction인 메서드
        f.run();
    }

    static MyFunction getMyFunction() { // 반환 타입이 MyFunction인 메서드
        MyFunction f = () -> System.out.println("f3.run()");
        return f;
    }

    public static void main(String[] args) {
        // 람다식으로 MyFunction의 run()을 구현
        MyFunction f1 = ()-> System.out.println("f1.run()");

        //람다식은 익명클래스의 객체다.
        //타입은 람다식과 동등한 메서드가 정의되어 있는 것이어야 한다.
        MyFunction f2 = new MyFunction() {  // 익명클래스로 run()을 구현
            public void run() {   // public을 반드시 붙여야 함
                System.out.println("f2.run()");
            }
        };

        MyFunction f3 = getMyFunction();

        f1.run();
        f2.run();
        f3.run();

        execute(f1);
        execute( ()-> System.out.println("run()") );
    }
}
결과
f1.run()
f2.run()
f3.run()
f1.run()
run()

람다식을 참조변수로 다룰 수 있다는 것은 변수처럼 메서드를 주고받는 것이 가능해진 것이다.
f2부분의 주석을 자세히보자. 사실상 메서드가 아니라 객체를 주고받는 것이라 근본적으로 바뀐건 없다.

java.util.function에서 제공하는 함수형 인터페이스

import java.util.function.*;

class Main{
    public static void main(String[] args) {
        Supplier<Integer> supply = () -> 1;
        System.out.println(supply.get());

        Consumer<Integer> consumer = v -> System.out.println(v);
        consumer.accept(2);

        Function<Integer, String> func = String::valueOf;
        System.out.println(func.apply(3));

        Predicate<Integer> func2 = v-> v>5;
        System.out.println(func2.test(4));
    }
}
결과
1
2
3
false

그 밖에도 java.lang.Runnable, BiConsumer<T, U>, BiPredicate<T, U>, BiFunctionM<T, U, R> 등이 있다.

        Predicate<Integer> p = i -> i < 100;
        Predicate<Integer> q = i -> i < 200;
        Predicate<Integer> r = i -> i%2 == 0;
        Predicate<Integer> notP = p.negate(); // i >= 100

        Predicate<Integer> all = notP.and(q.or(r)); // 100<=i && (i<200 || i% 2==0)
         System.out.println(all.test(150));       // true

Predicate<T>는 결합이 가능하다.

컬렉션 프레임웍의 함수형 인터페이스

(Collection).removeIf(Predicate<E> f);
(List).replaceAll(UnaryOperator<E> f);
(Iterable).forEach(Consumer<T> f);

(Map).forEach(BiConsumer<K,V> f);
(Map).compute(K key, BiFunction<K,V,V> f) //지정된 key값에 작업f 수행

컬렉션 프레임웍에서 함수형 인터페이스를 사용하는 메서드들이다.