람다식이란

람다식이란 메서드(함수)를 간단한 식(expression)으로 표현하는 방법이다.

간단한 식 즉, 간단하게 표현하고 싶은 방법이다.

작성 방법은 다음과 같다.

메서드의 이름과 반환 타입을 제거하고 -> 를 블록 {} 앞에 추가한다.

curly braces (중괄호) 안에 문장이 한 줄 일때는 중괄호를 생략한다.

그리고, 반환 타입일 경우 return도 생략 가능하다.

문장뒤에 세미콜론은 생략한다.

입력 매개 변수의 타입이 추론 가능하면 생략 가능하다.

Functional Interface (함수형 인터페이스)

자바스크립트 등 타 언어에서는 람다식을 익명 함수라고 한다.

그러나 자바에서는 함수가 객체 없이 홀로 존재할 수 없으므로 익명 클래스 안에 익명 함수로 표현을 해야 한다. 위에서 최종적으로 작성한 람다식을 다시 함수로 변환하게 되면 다음과 같다.

위 오른쪽을 Anonymous Class (익명 클래스)라고 부르며 익명 클래스란 객체의 선언과 생성을 동시에 한다는 것을 의미한다.

하지만 이 경우 객체 참조를 받아서 호출할 수가 없다.

그러므로 하나의 함수를 가진 인터페이스를 만든 다음에 익명 클래스를 생성해야 해당 함수를 호출 가능하다.

하나의 함수를 가진 인터페이스를 Functional Interface라고 한다. 위에서 @FunctionInterface 어노테이션을 붙이지 않아도 에러가 나지는 않는다. 하지만 붙이게 된다면 컴파일시에 함수가 하나밖에 없는지를 검사하고 두 개 이상이라면 컴파일시에 에러를 내게 해준다.

다시 위의 익명클래스를 람다식으로 변환하게 되면 다음과 같다. 앞에서 매개변수 타입을 생략한 이유도 참조 변수의 타입으로 추론할 수 있기 때문에 생략한것이며 리턴타입을 생략한것도 같은 이유에서다.

결론적으로 자바에서는 익명클래스와 람다식이 동일하다고 생각하면 된다.

람다식의 사용 예제를 살펴보자.

sort 함수의 두번째 파라메터는 FunctionalInterface 인 Comparator<T> 타입이다. 따라서 여기에는 익명클래스를 넣어줘야 한다. 익명클래스는 람다식과 동일하므로 다음과 같이 간단히 할 수 있다.

function 패키지

java.util.function 패키지에 다양한 functional interface가 만들어져 있다.

Functional Interface메서드설명
java.lang.Runnablevoid run()매개변수도 없고 반환값도 없음
Supplier<T>T get()매개변수는 없고 반환값만 존재
Consumer<T>void accept(T t)매개변수만 있고 반환값이 없음
Function<T, R>R apply(T t)매개변수와 반환값 모두 존재
Predicate<T>boolean test(T t)매개 변수가 있고, 반환 타입이 boolean
람다식을 작성하기 위해서는 해당 타입을 추론할 수 있는 Functional Interface가 존재하여야 하는데 매번 작성하기가 번거로우므로 위의 util 패키지의 함수를 활용할 수 있다.
Supplier<T>의 예를 보자. 우측 람다식을 보면 입력이 없고 반환값은 존재하므로 Supplier 타입으로 매핑할 수 있다.반환값은 int 이므로 Supplier<T> 에서 T 타입은 Integer로 추론이 된다.

Consumer<T> 의 예를 보자. 매개 변수는 있고 반환값이 없으므로 Consumer 타입으로 매핑가능하다. 입력 타입은 String도 가능하고 Integer도 가능하고 모든게 가능한데 만일 String 타입으로 매핑하면 Consumer<String> 이 되고, accept 함수를 호출할때 String 타입으로 매핑해야 한다.

Predicate<T> 의 예를 보자.

Function<T, R> 의 예를 보자.