/////
Search
Duplicate
7️⃣

람다, 메서드 참조 활용하기

사과 리스트를 다양한 정렬 기법으로 정렬하는 문제로 다시 돌아가서 3장에서 배운 람다를 통해 이 문제를 더 세련되고 간결하게 해결하는 방법을 보여준다.
사과 리스트 정렬 문제를 해결하기 위해 지금까지 배운 동작 파라미터화, 익명 클래스, 람다 표현식, 메서드 참조 등을 총동원한다.
최종 목표는 다음과 같은 코드를 만드는 것이다.
inventory.sort(comparing(Apple::getWeight));
Java
복사

1. 1단계 : 코드 전달

다행히 자바 8의 List API에서 sort 메서드를 제공하므로 정렬 메서드를 직접 구현할 필요는 없다.
그런데 어떻게 sort 메서드에 정렬 전략을 전달할 것일까? 먼저 sort 메서드의 시그니처를 살펴보자. 다음과 같다.
void sort(Comparator<? super E> c)
Java
복사
이 코드는 Comparator 인터페이스의 객체를 인수로 받아 두 리스트를 정렬하는 기준으로 삼는다. 즉 sort에 전달된 정렬 전략에 따라 sort의 동작이 달라질 것이다.
1단계 코드는 다음과 같이 완성할 수 있다.
public class AppleComparator implements Comparator<Apple> { public int compare(Apple a1, Apple a2) { return a1.getWeight().compareTo(a2.getWeight()); } } inventory.sort(new AppleComparator());
Java
복사

2. 2단계 : 익명 클래스 사용

: 한 번만 사용할 Comparator를 위 코드처럼 구현하여 선언하는 것보다는 익명 클래스를 이용하는 것이 좋다.
inventory.sort(new Comparator<Apple>() { public int compare(Apple a1, Apple a2) { return a1.getWeight().compareTo(a2.getWeight()); } });
Java
복사

3. 3단계 : 람다 표현식 사용

: 하지만 아직도 코드가 꽤나 장황해 보인다. 자바 8에서는 람다 표현식이라는 경량화된 문법을 이용해서 코드를 전달할 수 있다.
: 함수형 인터페이스를 사용할 수 있는 곳 어디에서나 람다 표현식을 사용할 수 있음을 우리는 이미 알고 있다.
: 추상 메서드의 시그니처는 람다 표현식의 시그니처를 저의한다. Comparator의 함수 디스크립터는 (T, T) → int다. 우리는 사과를 정렬할 것이므로 (Apple, Apple) → int로 표현할 수 있다.
inventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));
Java
복사
: 여기서 자바 컴파일러는 람다 표현식이 사용된 컨텍스트를 활용해서 람다의 파라미터 형식을 추론한다고 설명했다. 따라서 코드를 다음과 같이 더 줄일 수 있다.
inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));
Java
복사
: 이 코드의 가독성을 더 향상시킬 수는 없을까? Comparator는 Comparable 키를 추출해서 Comparator 객체로 만드는 Function 함수를 인수로 받는 정적 메서드 comparing을 포함한다.
: 즉 다음처럼 comparing 메서드를 사용할 수 있다.
Comparator<Apple> c = Comparator.comparing((Apple a) -> a.getWeight());
Java
복사
: 이제 다음처럼 코드를 간소화할 수 있다.
import static java.util.Comparator.comparing; inventory.sort(comparing(apple -> apple.getWeight()));
Java
복사

4. 4단계 : 메서드 참조 사용

: 메서드 참조를 이용하면 람다 표현식의 인수를 조금 더 깔끔하게 전달할 수 있다는 것도 설명햇다.
import static java.util.Comparator.comparing; inventory.sort(comparing(Apple::getWeight));
Java
복사
: 드디어 최적의 코드에 도달했다. 자바 8 이전의 코드와 비교해서 뭐가 달라졌을까?
: 먼저 코드가 짧아졌다. 그리고 코드의 의미도 명확해졌다. 즉 코드 자체로 Apple을 weight 별로 비교해서 inventory를 sort하라는 의미를 전달할 수 있다.