: 메서드를 하나의 식(expression)으로 표현한 것. 그래서 변수처럼 사용이 가능해진다.
- JEDK1.8에 추가된 문법.
- 자바에 함수형 패러다임을 갖도록 한 문법.
- 자바에서는 기본적으로 메서드를 만들려면 클래스를 만들고, 객체도 생성해야하는데, 이 모든 과정을 생략 가능하게 해준다.
함수형 인터페이스
: 람다식을 변수로 받을 수 있는 참조변수
@FunctionalInterface
를 사용해 함수형 인터페이스임을 알린다.단 하나의 abstract 메소드만을 가질 수 있다. 그래야 람다식과 인터페이스의 메서드가 1:1로 연결될 수 있기 때문이다. (default, static 제외)
Comparator
내부를 확인해보면 디폴트 메소드를 제외하고는compare
라는 메서드 하나 있다. (equals()
는Object
클래스로부터 받은 것)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
@FunctionalInterface public interface FooInterface { int plus(int a, int b); } // --- 아래와같이 사용 FooInterface f = (x, y) -> x + y; // A int result = f.plus(5, 3); // B FooInterface f = new FooInterface() { @Override public int plus(int a, int b) { return 0; } };
- A와 B는 같다. 함수형 인터페이스를 구현하는
public int~~
부분을 람다식으로 줄여준 버전이 A
람다와 클로저
: 코드를 실행하는 런타임은 자유변수를 “어떤 박스에 넣고 잠가서” 나중에 함수가 실제로 실행할 때, 사용할 수 있도록 만든다.
- 함수는 변수가 선언된 바깥 부분의 코드가 이미 실행되고 사라진 한참 후에 실행될지도 모른다. 그럼에도 불구하고 해당 변수의 당시의 상태를 기억하는 클로저의 성질 덕분에 람다에서 외부 변수 참조가 가능하다.
java.util.function
java.util.function
패키지에 일반적으로 쓰이는 형식의 메서드가 구현되어있으니, 매번 새롭게 정의하지 말고 이 패키지의 인터페이스를 활용할 것이 권장된다.- 이 패키지에 존재하는 함수형 Interface들은 컬렉션 프레임워크에서 몇 메서드들의 매개변수로 받고있다.
인터페이스들
Function<T, R>
:apply()
메서드를 사용하는 가장 일반적인 함수. 매개변수 하나, 리턴값이 있다.Predicate<T>
:test()
메서드 사용. boolean을 반환한다는 점이 Function과 다르다. 조건식을 람다식으로 표현하는데 꽤 많이 사용되는 편Consumer<T>, BiConsumer<T, U>
:accept()
메서드를 사용. 매개변수가 1 or 2개인 것이 다르다. 이름 그대로 사용하는 것이라서 반환값이 없다.Supplier<T>
:get()
이름 그대로 공급자. consumer와 반대로 매개변수가 없고 반환값만 있다.UnaryOperator<T>, BinaryOperator<T>
: 매개변수와 반환형이 일치T -> T
. Binary는 매개변수를 두개 받는다.- 이외에도
DoubleToIntFunction
,ToIntFunction<T>
등 지네릭이 아닌 기본형(래퍼클래스)을 다루는Function
들도 존재한다.
합성
수학에서 f(g(x)) 하는 것처럼, 함수형 인터페이스를 합성할 수 있다.
1 2 3 4 5 6 7 8 9
Function<String, Integer> f = x -> 5; Function<Integer, String> g = x -> x.toString(); Function<String, String> h = f.andThen(g); // g.compose(f) Predicate<Integer> p = i -> i > 100; Predicate<Integer> q = i -> i < 200; Predicate<Integer> r = i -> i % 2 == 0; Predicate<Integer> all = p.and(q.or(r));
메서드 참조 (A::b)
: String::equals
과 같은 더 간결한 문법도 람다식에 해당한다.
‘클래스이름::메서드이름’ 혹은 ‘참조변수::메서드이름‘의 방식으로 가능하다
1 2 3 4 5 6 7 8 9
() -> new myClass(); (a, b) -> new myClass(a, b); x -> new int[x]; // 위의 expression이 아래로 가능 myClass::new; int[]::new;
Reference)
자바의 정석 3판
자바 개발자를 위한 함수형 프로그래밍