람다식은 익명 함수답게 메소드에서 이름과 반환 타입을 제거하고
매개변수 선언부과 메소드 몸통{ } 사이에 ->를 추가한다.
// 일반 메소드 :
반환타입 메소드이름(매개변수 선언) {
문장들
}
// 람다식으로 작성 :
(매개변수 선언) -> {
문장들
}
예를 들어, 두 값 중 큰 값을 반환하는 메소드 max를 람다식으로 변환하면 이렇게 된다.
// 일반 메소드 :
int max(int a, int b) {
return a > b ? a : b;
}
// 람다식으로 작성 :
(int a, int b) -> {
return a > b ? a : b;
}
;를 붙이지 않는다. (int a, int b) -> { return a > b ? a : b; }
// return문 생략
(int a, int b) -> a > b ? a : b
(int a, int b) -> a > b ? a : b
// 매개변수의 타입 생략
(a, b) -> a > b ? a : b
(a) -> a * a
(int a) -> a * a
// 괄호( ) 생략
a -> a * a
int a -> a * a // 에러. 매개변수의 타입이 있음
;를 붙이지 않는다. (int a) -> { System.out.println("a : " + a); }
// 괄호{ } 생략
(int a) -> System.out.println("a : " + a)
(int a, int b) -> return a > b ? a : b // 에러. return문은 괄호 생략 X
타입 f = (int a, int b) -> a > b ? a : b
위의 람다식을 보자면, 람다식을 그저 변수의 값으로 선언하는 것처럼 보인다.
그러나 자바에서 메소드는 단독으로 선언될 수 없다. (클래스에 포함되어 있어야 한다)
객체를 통해 메소드를 호출해야 하는 것처럼 람다식도 이름이 없는 객체를 통해 호출되는 것이다.
정확히 말하면 인터페이스의 익명 구현 객체로 표현한 것이다.
예를 들어, max라는 메소드가 정의된 MyFunction 인터페이스가 있다고 가정하자.
interface MyFunction {
public abstract int max(int a, int b);
}
그러면 이 인터페이스를 구현한 익명 클래스의 객체는 다음과 같이 생성할 수 있다.
MyFunction f = new MyFunction() {
public int max(int a, int b) {
return a > b ? a : b;
}
}; // 익명 클래스는 끝에 세미콜른을 붙여 주어야 함
int big = f.max(3, 5); // 익명 객체의 메소드 호출
MyFunction 인터페이스의 메소드를 구현과 동시에 구현한 클래스의 객체를 생성!!
이를 익명 구현 객체라고 한다.
인터페이스의 max 메소드는 람다식과 선언부가 일치한다. 그래서 위 코드를 람다식으로 대체할 수 있다.
MyFunction f = (int a, int b) -> a > b ? a : b;
int big = f.max(3, 5);
위에서 익명 객체를 람다식으로 대체 가능한 이유는
실제로는 람다식도 익명 객체이고, MyFunction 인터페이스를 구현한 익명 객체의 메소드 max()와 람다식의 매개변수 타입과 개수 그리고 반환값이 일치하기 때문이다.
위의 인터페이스처럼 하나의 메소드만이 선언되어 람다식을 다루기 위해
정의된 인터페이스를 함수형 인터페이스라고 부른다.
@FunctionalInterface
interface MyFunction { // 함수형 인터페이스 MyFunction 정의
public abstract int max(int a, int b);
}
단, 함수형 인터페이스를 정의하기 위해서는 조건이 있다.
람다식과 인터페이스의 메소드가 1대1로 연결되어야 하기 때문에 하나의 메소드만 정의되어 있어야한다.
주의할 점은 static 메소드와 default 메소드는 개수에 포함되지 않는다.
@FunctionalInterface 어노테이션은 컴파일러가 함수형 인터페이스를 올바르게 정의했는지 확인해주는 기능이므로, 되도록이면 붙이자!
기존에는 인터페이스의 메소드 하나를 구현하는데에도 복잡했다.
List<String> list = Arrays.sort("aaa","bbb","abc","cca","aca");
Collections.sort(list, new Comparator<String>() {
public int compare(String s1, String s2) {
return s2.compareTo(s1);
}
}
함수형 인터페이스 Comparator의 compare 메소드를 저렇게 구현했어야 했다.
그러나 람다식을 사용하면 더 간단히 처리할 수 있게 되었다.
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));