1. 람다식(Lambda Expression) 이란?
- Stream 연산들은 매개변수로 함수형 인터페이스를 받도록 되어있습니다.
- 람다식은 반환값으로 함수형 인터페이스를 반환하고 있습니다.
- 그렇기 때문에 Stream API를 정확하기 위해서는 람다식과 함수형 인터페이스에 대해서 알고있어야 합니다.
람다식은?
- 람다식(Lambda Expression)이란 함수를 하나의 식(Expression)으로 표현한 것입니다.
- 함수를 람다식으로 표현하면 메서드의 이름이 필요 없기 때문에 람다식은 , 익명 함수(Anonymous Function)의 한 종류라고 볼 수 있습니다.
익명함수(Anonymous Function)이란 함수의 이름이 없는 함수로, 익명함수들은 모두 일급 객체입니다.
일급 객체인 함수는 변수처럼 사용가능하며 매개 변수로 전달이 가능하는 등의 특징을 가지고 있습니다.
기존의 방식에서 함수를 선언할 때
public String hello(){
return "HELLO WORLD!";
}
람다 방식으로 바꿀때
(매개변수,...) -> (실행문 ...)
() -> "HELLO WORLD!";
- 이렇게 람다식이 등장하게 된 이유는 불필요한 코드를 줄이고, 가독성을 높이기 위함입니다.
- 그렇기 때문에 함수형 인터페이스의 인스턴스를 생성해서 함수를 변수처럼 선언하는 람다식에서는 메서드의 이름을 불필요하다고 여겨져 이를 사용하지 않습니다.
- 대신 컴파일러가 문맥을 살펴 타입을 추론합니다.
- 또한 람다식으로 선언된 함수는 1급 객체이기 때문에 Stream API 의 매개변수로 전달이 가능해집니다.
람다식의 특징
- 람다식 내에서 사용되는 지역변수는 fianl 이 붙지 않아도 상수로 간주한다.
- 람다식으로 선언된 변수명은 다른 변수명가 중복될 수 없다.
람다식의 장점
- 코드를 간결하게 만들 수 있습니다.
- 식에 개발자의 의도가 명확히 드러나 가독성이 높아집니다.
- 함수를 만드는 과정없이 한번에 처리할 수 있어 생산성이 높아집니다.
- 병렬 프로그래밍이 용이합니다.
람다식의 단점
- 람다를 사용하면서 만든 무명함수는 재사용이 불가능합니다.
- 디버깅이 어렵습니다.
- 람다는 남용하면 비슷한 함수가 중복 생성되어 코드가 지저분해질 수 있습니다.
- 재귀로 만들경우에 부적합합니다.
결론
- 무조건 람다가 좋다는 보장은 없습니다.
- 상황에 따라서 필요에 맞는 방법을 사용하는 것이 중요합니다.
함수형 인터페이스(Functional Inteferface)란?
함수형 인터페이스
- 람다식으로 순수 함수를 선언할 수 있게 되었습니다.
- 하지만 java는 기본적으로 객체지향 언어이기 때문에 순수 함수와 일반 함수를 다르게 취급하고 있스빈다.
- java에서는 이를 구분하기 위해 함수형 인터페이스가 등장 하게 되었습니다.
- 함수형 인터페이스란 함수를 1급 객처럼 다룰 수 있게 해주는 어노테이션으로 인터페이스에 선언하여 단 하나의 추상 메서드만을 갖도록 제한하는 역할을 합니다.
- 함수형 인터페이스를 사용하는 이유는 java 의 람다식이 함수형 인터페이스를 반환하기 때문입니다.
예시
- 예를들어 두 값 중 큰 값을 구하는 익명함수를 개발하였다고 가정합니다.
public class Lambda{
public static void main(String[] args){
System.out.println(new MyLambdaFunction(){
public int max(int a, int b){
return a> b ? a: b;
}
}.max(3,5);
}
}
- 하지만 함수형 인터페이스의 등장으로 우리는 함수를 변수처럼 선언할 수 있게 되었고, 코드 역시 간결하게 작성할 수 있게 되었습니다.
- 함수형 인터페이스를 구현하기 위해서는 인터페이스를 개발하여 그 내부에는 1개 뿐인 abstract 함수를 선언하고, 위에는 @FuncionalInterface 어노테이션을 붙여주면 됩니다.
@FunctionalInterface
interface MyLambdaFunction {
int max(int a, int b);
}
public class Lambda {
public static void main(String[] args) {
MyLambdaFunction lambdaFunction = (int a, int b) -> a > b ? a : b;
System.out.println(lambdaFunction.max(3, 5));
}
}
- 이제 우리는 java 8 이전에 사용했던 익명함수들을 람다식으로 변경해 코드를 줄일 수 있게 되었고,
여기서 놓치지 말아야 하는것은 람다식으로 생성된 순수 함수는 함수혀 인터페이스로만 선언이 가능하다는 점입니다.
- 또한 @FunctionalInterface는 해당 인터페이스가 1개의 함수만을 갖도록 제한하기 때문에, 여러개의 함수를 선언하면 컴파일 에러가 발생한다는 점입니다.