람다 표현식(lambda expression)이란 자바에서 함수형 프로그래밍(functional programming)을 구현하는 방식이다. Java8부터 지원하고 있으며, 클래스를 생성하지 않고 함수의 호출만으로 기능을 수행할 수 있다.
함수형 프로그래밍이란?
순수 함수(pure function)을 구현하고 호출함으로써 외부 자료에 부수적인 영향을 주지 않고 매개 변수만을 사용하도록 만든 함수이다. 입력 받은 자료를 기반으로 수행되고 외부에 영향을 미치지 않으므로 병렬 처리가 가능하며, 안정적이고 확장성 있는 프로그래밍 방식이다.
람다 표현식은 익명 함수를 만드는 형태로 구현한다. 람다식 문법은 기본적으로 (매개변수) -> {실행문;}을 따르는데 예제로 아래 add 함수 구현을 살펴보자.
(int x, int y) -> {return x + y;}
상황 별 람다 표현식 문법
str -> {System.out.println(str);}
(int x, int y) -> {System.out.println(x+y);}
str -> System.out.println(str);
str -> {return str.length;}
(int x, int y) -> x + y;
str -> str.length;
함수형 인터페이스는 1개의 추상 메소드를 갖는 인터페이스이며 자바의 람다 표현식은 함수형 인터페이스로만 사용이 가능하다. 함수형 인터페이스를 작성할 때에는 @FunctionalInterface annotation을 사용하는데, 이것은 해당 인터페이스가 함수형 인터페이스인지 컴파일 단계에서 검사한다. Annotation 없이도 작동하는데, 인터페이스 검증 및 유지보수 측면에서 붙여주는 것이 좋다.
아래는 함수형 인터페이스 예제이다.
@FunctionalInterface
public interface StringConcat {
public void makeString(String s1, String s2);
}
함수형 인터페이스을 기반으로, 람다 표현식을 사용하여 함수를 구현하는 방법을 클래스 이용 방식, 익명 내부 클래스로 함수를 구현하는 방법과 비교해보자.
람다 표현식으로 함수 구현
public class TestStringConcat {
public static void main(String[] args) {
StringConcat concat = (s1, s2) -> System.out.println(s1 + " " + s2);
concat.makeString("Hello", "Java"); // Hello Java
}
}
클래스 이용 방식으로 함수 구현
public class StringConcatImpl implements StringConcat {
@Override
public void makeString(String s1, String s2) {
System.out.println(s1 + " " + s2);
}
}
public class TestStringConcat {
public static void main(String[] args) {
StringConcatImpl sImpl = new StringConcatImpl();
sImpl.makeString("Hello", "Java"); //Hello Java
}
}
익명 내부 클래스로 함수 구현
public class TestStringConcat {
public static void main(String[] args) {
StringConcat concat2 = new StringConcat() {
@Override
public void makeString(String s1, String s2) {
System.out.println(s1 + " " + s2);
}
};
concat2.makeString("Hello", "Java");
}
}
위 예제들에서 알 수 있듯이 람다 표현식으로 함수를 구현하는 것이 가장 간단한 방식이기 때문에, 함수 구현에 있어서 람다 표현식을 많이 사용한다.