람다식은 메서드를 하나의 식으로 표현한 것이다. 람다식으로 메서드를 표현하면 메서드의 이름과 반환값이 없어지므로 '익명 함수'이라고도 한다.
//메서드
int max(int a,int b) {
return a > b ? a : b;
}
//람다식
(int a, int b) -> { return a > b ? a : b };
위의 예시는 max 메서드를 람다식으로 변환한 것인데 메서드 이름과 반환형 타입이 없는 것 외에는 별 차이 점이 없어보인다. 하지만 람다식에서는 불필요한 키워드를 생략가능한 경우가 많다.
- 반환값이 있는 경우 return 대신 식으로 표현가능
(int a, int b) -> { return a > b ? a : b; } // (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; // a -> a*a; (int a) -> a*a; // int a -> a*a; 에러
괄호{}안의 문장이 하나일 때는 return문을 생략가능
(String name, int i) -> { System.out.println(name + "-" + i); } //(String name, int i) -> System.out.println(name + "-" + i);
괄호{} 안의 문장이 return문일 경우 괄호{} 생략불가.
그럼 람다식에 대해 좀 더 자세히 알아보자. 람다식은 대체 어떻게 호출이 되는 것일까? 자바에서는 메소드 호출을 하기위해서는 클래스가 필요하고 클래스 참조를 이용하여 메소드를 호출하는데 말이다.
(int a, int b) -> a > b ? a : b;
//익명 객체의 max메소드와 람다식의 선언부와 유사하다.
new Object() {
int max(int a, int b) {
return a > b ? a : b;
}
}
아래의 인터페이스와 익명 객체를 살펴보자.
@FunctionalInterface
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;
}
}
MyFunction 인터페이스의 추상메소드 max의 선언부와 람다식 (int a, int b) -> a > b ? a : b와 동등하므로 아래와 같이 람다식을 표현할 수 있다. 아래의 코드는 실제로도 동작하는데 즉, 람다식은 어느 인터페이스의 익명 객체라는 것이다.
MyFunction f = (int a, int b) -> a > b? a : b
MyFunction과 같이 람다식을 다루기 위한 인터페이스를 '함수형 인터페이스'라고 정의하며 자바에서는 몇몇 이러한 인터페이스를 정의해 두었다. 익명객체로 사용하면 되지 굳이 람다식이 필요할까 하겠지만 아래의 코드를 보면 가독성 차이가 나는 것을 느낄 수 있다.
//익명 객체를 이용
Collections.sort(list, new Comparator<String>() {
public int compare(String s1, String s2) {
return s2.compareTo(s1);
}
}
//람다식 이용
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));