💡 함수형 인터페이스(Functional interface)
람다식을 다루기 위한 인터페이스. 오직 하나의 추상 메서드만 정의되어 있다.
Function<Integer[], Boolean> fn = a -> a[0] > a[1];
→ integer 배열을 받아서 boolean을 리턴
public static void main(String[] args) {
Integer[] arr = new Integer[] {2, 7, 4, 9, 10, 223, 111, 23, 1, 3, 39};
Function<Integer[], Boolean> fn = a -> a[0] > a[1];
System.out.println(fn.apply(arr));
}
false
Predicate는 Function의 변형으로, 반환타입이 boolean이라는 것만 다르다. Predicate는 조건식을 람다식으로 표현하는데 사용한다.
Predicate<String> isEmptyStr = s -> s.length() == 0;
String s = "";
if(isEmptyStr.test(s)){
System.out.println("Empty");
}
매개변수의 개수가 2개인 함수형 인터페이스는 이름 앞에 접두사 ‘Bi’가 붙는다.
BiFunction<Integer, Integer, Boolean> biFunction = (a, b) -> a > b;
→ 앞에 두개 타입을 Integer a, Integer b로 받아서 True or False로 리턴
두 개 이상의 매개변수를 갖는 함수형 인터페이스가 필요하다면 직접 만들어서 쓴다. 3개의 매개변수를 갖는 함수형 인터페이스는 아래와 같다.
@FunctionalInterface
interface TriFunction<T, U, V, R> {
R apply(T t, U u, V v)
}
컬렉션 프레임웍의 인터페이스에 다수의 디폴트 메서드에 함수형 인터페이스를 사용한다.
//1. list의 모든 요소를 출력
list.forEach(i -> System.out.print(i+", ");
//2. list에서 2 또는 3의 배수를 제거한다.
list.removeIf(x -> x%2==0 || x%3==0);
//3. list의 각 요소에 10을 곱한다.
list.replaceAll(x -> x*10);
//4. map의 모든 요소를 출력
map.forEach((k, v) -> System.out.print("{"+k+","+v+"}, "))
지금까지의 함수형 인터페이스는 모두 지네릭 타입이어서 기본형 타입의 값을 처리할 때도 wrapper 클래스를 사용해왔다. 그러나 기본형 대신 래퍼클래스를 사용하는 것은 비효울적이다. 그래서 효율적으로 처리할 수 있도록 기본형 을 사용하는 함수형 인터페이스들이 제공된다.
람다식이 하나의 메서드만 호출하는 경우에는 ‘메서드 참조 (method reference)’라는 방법으로 람다식을 간략히 할 수 있다.
메서드 참조에서는 람다식의 일부가 생략되지만, 컴파일러는 생략된 부분을 우변의 메서드 선언부로부터, 또는 좌변의 Function 인터페이스에 지정된 지네릭 타입으로부터 쉽게 찾아낼 수 있다.
Function<String, Integer> f = (String s) -> Integer.parseInt(s); //람다식
Function<String, Integer> f = Integer::parseInt; //배열참조
이미 생성된 객체의 메서드를 람다식에서 사용한 경우 클래스 이름 대신 객체의 참조변수를 사용한다.
Function<String, Boolean> f = (x) -> obj.equals(x);
Function<String, Boolean> f = obj::equals;
생성자의 메서드 참조
Sypplier<MyClass> s = () -> new MyClass();
Sypplier<MyClass> s = MyClass::new;
Function<Integer, MyClass> f = (i) -> new MyClass(i);
Function<Integer, MyClass> f = MyClass::new;
배열 생성
Function<Integer, int[]> f = x -> new int[x];
Function<Integer, int[]> f = int[]::new;