람다식
람다식(Lambda expression)은 메서드를 하나의 식으로 표현한 것이다. 람다식을 익명 함수라고도 부른다.
람다식의 기본 형태는 메서드의 이름과 반환 타입을 제거하고 매개 변수 선언부와 몸통 사이에 -> 을 추가한다.
/*
int max(int a, int b) {
return a > b ? a : b;
}
*/
(int a, int b) -> { return a > b ? a : b; }
함수형 인터페이스
람다식은 익명 클래스와 동등하다. 익명 클래스 선언 시 익명 객체를 반환하는데 람다식도 마찬가지로 익명 객체를 반환한다. 익명 클래스로 만든 익명 객체는 부모 클래스 타입 또는 인터페이스 타입의 참조 변수로 받아 사용할 수 있었다. 하지만 익명클래스에서 부모를 상속받아 추가적인 멤버를 정의하는 일은 없다. 어차피 추가한 멤버를 사용하지 못하기 때문이다. 따라서 인터페이스로 다루는게 자연스럽다. 그래서 람다는 인터페이스만을 통해 다루기로 했으며, 람다식을 다루기 위한 인터페이스를 함수형 인터페이스라고 한다. 함수형 인터페이스는 람다식에 대응될 하나의 추상 메서드만을 가진다. 반면에 static 메서드와 default 메서드의 개수에는 제약이 없다.
함수형 인터페이스 예시
@FunctionalInterface
interface MyFunction {
public abstract int max(int a, int b);
}
함수형 인터페이스을 통한 람다 사용
public class Main {
public static void main(String[] args) throws IOException {
MyFunction f1 = (int a, int b) -> a > b ? a : b;
System.out.println(f1.max(3,5));
/*
MyFunction f1 = new MyFunction() {
@Override
public int max(int a, int b) {
return a > b ? a : b;
}
};
System.out.println(f1.max(3,5));
*/
}
}
라이브러리 함수를 보면 인자에 함수형 인터페이스가 있는 경우가 있는데, 이 경우 람다식으로 쉽게 작성이 가능하다. list의 sort 메서드는 인자는 Comparator 함수형 인터페이스 타입이다.
List<String> list = Arrays.asList("abc", "aaa", "bbb", "ddd", "aaa");
list.sort((a, b) -> a.compareTo(b));
람다식 생략
아래의 세 가지 규칙으로 람다식을 더 짧게 만들 수 있다.
1. 괄호 안의 문장이 하나 일때는 괄호 { }를 생략하고 return 문장일 경우 return도 생략이 가능하다.
(int a, int b) -> a > b ? a : b
2. 람다식의 선언된 매개변수의 타입이 추론 가능하다면 타입 생략이 가능하다. 컴파일러는 함수형 인터페이스를 통해 타입 추론을 할 수 있다.
(a, b) -> a > b ? a : b
3. 매개 변수가 하나일 경우 소괄호를 생략할 수 있다.
a -> System.out.prinln(a)
java.util.function 패키지
java.util.function 패키지에는 자주 쓰이는 함수형 인터페이스가 정의되어 있다. 매번 새로운 함수형 인터페이스를 정의하지 말고, 가능하면 이 패키지의 인터페이스를 활용하는 것이 좋다. 그래야 함수형 인터페이스의 정의된 메서드 이름도 통일되고, 재사용성이나 유지보수 측면에서도 좋다.
기본적인 함수형 인터페이스
매개변수가 2개인 함수형 인터페이스
이름 앞에 접두사 'Bi'가 붙는다.
Function의 변형 인터페이스
이중콜론 문법
람다식이 실행 구문에서 하나의 메서드만 호출하고, 매개 변수를 메서드의 인자로 넣어주는 경우 이중콜론 문법으로 람다식을 더 짧게 만들 수 있다.
예를 들어 아래와 같이 생략이 가능하다.
Function<String, Integer> f1 = s -> Integer.parseInt(s);
//이중콜론 문법 적용
Function<String, Integer> f2 = Integer::parseInt;
메서드 종류에 따라 아래와 같이 이중콜론 문법을 적용할 수 있다.
//static 메서드
(x) -> className.method(x) //람다
ClassName::method //메서드 참조
//인스턴스 메서드
(obj, x) -> obj.method(x) //람다
ClassName::method //메서드 참조
//특정 객체 인스턴스 메서드
(x) -> obj.method(x) //람다
obj::method //메서드 참조
또한 생성자 호출, 배열을 생성하는 람다식에도 이중콜론 문법을 적용할 수 있다.
//Supplier<MyClass> s = () -> new MyClass();
Supplier<MyClass> s = MyClass::new;
//Function<Integer, int[]> f = x -> new int[x];
Function<Integer, int[]> f = int[]::new;
'Java > Basic' 카테고리의 다른 글
자바 예외 처리 (0) | 2023.06.05 |
---|---|
Java 익명 클래스 (0) | 2023.04.04 |
Regex (0) | 2023.01.23 |
[JVM - 2] ClassLoader (0) | 2022.10.25 |
Java 정렬 (0) | 2022.09.07 |