람다표현식(lambda expression)
람다표현식은 일반적인 메소드 대신 하나의 식으로 표현하는 것이다. 즉, 즉석에서 사용할 임의의 메소드 하나를 만든다고 보면 된다. 익명함수(anonymous function)이라고도 한다.
(매개변수...) -> {실행문;}; 이런식으로 만들어주면 된다.
예를 들어, x,y를 더하는 함수라고 하면 (int x, int y)->{return x+y;}; 이런느낌이다. 안팎으로 ;을 붙여줘야한다.
람다식의 장점
1. 코드가 간결해진다.
2. 코드 가독성이 높아진다.
3. 생산성이 높아진다.(멀티스레드를 활용한 병렬처리)
람다식의 단점
1. 코드 재사용이 불가능하다(익명)
2. 디버깅이 어렵다.
3. 재귀함수로는 맞지 않는다.
메소드같은 경우 디버깅용 코드를 작성하거나 중단점을 잡아가면서 디버깅을 진행하는데 람다식은 그러기 쉽지않다는 의미이다.
** 특징으로 람다식 내에서 사용되는 지역변수는 final이 붙지 않아도 상수로 간주된다. 람다식에서 선언된 변수명은 다른 변수명과 중복될 수 없다. **
인터페이스에 추상메소드가 하나인 경우에 사용이 가능하다.(두개면 제한된다.)
먼저 인터페이스를 정의하고 이를 구현하는 식으로 사용하는 것이다. return이 있으면 괄호를 생략할 수 없다.
구현해야할 추상메소드가 하나만 정의된 인터페이스는 함수형 인터페이스라고 한다. @FunctionalInterface가 붙어있다. 이게 붙어있으면 컴파일러에서 추상메소드를 갖고있는 인터페이스인지 검사하게 된다.
내부에 스태틱, 디폴트 메소드 개수에는 제약이 없다.
자주 사용하는 함수형 인터페이스는 java.util.function 패키지에서 제공해준다.(JDK 1.8부터)
Interface | Function Descriptor | Abstract Method | 설명 |
Predicate<T> | (T) -> boolean | boolean test(T t); | 객체 T를 매개변수로 받아 처리하고 boolean 데이터형을 반환 |
Consumer<T> | (T) -> void | void accept(T t); | 객체 T를 매개변수로 받아 처리하고 반환값은 없음. andThen()이라는 함수를 제공해주기 때문에 accept()메소드로 처리하고 andThen()메소드로 후처리가 가능 |
Function<T, R> | (T) -> R | R apply(T t); | 객체 T를 매개변수로 받아 R타입으로 반환 compose() 메소드로 연쇄적으로 실행해주는 함수 제공. apply()메소드 이전에 동작한다. |
Supplier<T> | () -> T | T get(); | 매개변수가 없이 반환값만 갖는다. |
UnaryOperator<T> | (T) -> T | T apply(T t); | 매개변수 T를 받아 동일한 타입으로 반환 |
람다식 예시1(우선순위 큐 비교, 정렬)
// 1. Integer 내림차순 정렬(Max Heap)
PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> y - x);
// 2. 맵에서 빈도가 같은 경우는 key 기준으로 정렬, 다른 경우는 빈도 수 기준으로 정렬
PriorityQueue<Map.Entry<Integer, Integer>> pq =
new PriorityQueue<>((x, y) -> y.getValue() == x.getValue() ?
x.getKey() - y.getKey() : y.getValue() - x.getValue());