Comparator
의 comparing()
을 사용하면 List의 원소들을 비교하여 정렬하는 것을 간단한 방식으로 구현할 수 있게 해준다.
우선 comparing()
을 사용하지 않는 방법을 살펴보자.
예를 들어 appleList
라는 List에 담긴 Apple
을 무게순으로 정렬한다고 가정하자.
Collections.sort(appleList, new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o1.getWeight() - o2.getWeight();
}
});
위와 같이 익명 클래스를 사용하여 구현할 수 있을 것이다.
또한 Apple
이라는 객체가 Comparable
을 구현하여 compareTo()
를 오버라이딩 하는 방법도 있을 것이다.
@Getter
public class Apple implements Comparable<Apple> {
private int weight;
...
@Override
public int compareTo(Apple o) {
return weight - o.weight;
}
}
익명 클래스를 사용하면, 코드가 너무 길고 복잡하지 않은가? (물론 람다 쓰면 더 짧지만 극적인 비교를 위해 ㅎㅎ)
Comparable
을 구현한다면, 정렬 시에 다른 조건이 필요한 경우 다시 정의해야 하며, 정렬 시점에서 어떠한 기준으로 정렬하는지 알 수 없어 가독성이 좋지 않을 수 있다.
이러한 문제점을, Java 8에서 추가된 comparing()
을 사용하면 간단하게 구현할 수 있다.
메소드 참조와 comparing()
을 사용하면 코드의 양을 크게 줄일 수 있다.
appleList.sort(comparing(Apple::getWeight));
6줄이었던 코드가 1줄로 감소하였고, 가독성이 크게 향상되었다.
그렇다면 Comparator
의 comparing()
은 어떻게 동작하는 것일까?
내부적으로 전달 받은 Function
으로 값을 추출하여 비교하는 Comparator
를 반환해준다.
Apple
의 무게는 int이기 때문에 comparing()
대신 primitive specialization한 comparingInt()
를 사용할 수 있는데, 여기를 참고하면 성능 차이는 미비하다고 한다.
-128 ~ 127은 Integer의 Cache 구간인 영향도 있을 것이다.
결론적으로 래퍼 클래스를 사용하고 있는데 primitive specialization를 사용하고자 한다면 언박싱 비용이 더 발생할 수도 있으므로, 성능이 매우 중요하다면 벤치마킹을 해보는 것이 좋을 것 같다.
잘 보았습니다!