Comparable과 Comparator는 언제 써야할까?
Comparable과 Comparator는 모두 객체를 비교할 때 사용하는 인터페이스입니다.
public interface Comparable<T> {
public int compareTo(T o);
}
public interface Comparator<T> {
int compare(T o1, T o2);
}
compareTo 메서드와 compare 메서드를 비교해보면 매개변수의 개수가 다릅니다.
이로부터 알 수 있는 사실은 Comparable의 compareTo 메서드의 비교의 대상이 자기 자신과 매개변수 o1이고, Comparator의 compare 메서드의 비교 대상은 매개변수 o1, o2 입니다.
즉, 본질적으로 비교한다는 것 자체는 같지만 비교 대상이 다릅니다.
Comparable 인터페이스
Comparable 인터페이스에는 compareTo() 메서드가 있습니다.
public interface Comparable<T> {
public int compareTo(T o);
}
위에서 언급했다싶이, compareTo(T o) 메서드의 매개변수가 1개이고 이는 자기 자신과 매개변수 객체를 비교하는 것입니다.
수들은 크다 작다 를 비교할 수 있는데, 객체는 무엇을 기준으로 비교할 수 있을까요?
Comparable 인터페이스의 compareTo(T o) 메서드를 구현하여 그 기준을 만들어줄 수 있습니다.
public class Person implements Comparable<Person>{
private int age;
public Person(int age) {
this.age = age;
}
// 오름차순
@Override
public int compareTo(Person o) {
if(this.age - o.age > 0){
return 1;
}else if(this.age == o.age){
return 0;
}else{
return -1;
}
}
...
}
"자기자신과 매개변수 o를 비교하였을 때 반환값이 양수일 때 자기자신이 더 큰 것" 이라고 이해하면 좋을 듯 싶습니다.
Collections의 sort 메서드를 이용해 List를 정렬해줄 수 있습니다. 이를 테스트해보면 나이가 더 많은 person1이 앞에 위치한 것을 확인할 수 있습니다.
Comparator 인터페이스
Comparator 인터페이스에는 compare() 메서드가 있습니다.
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
compare(T o1, T o2) 메서드는 두 개의 매개변수를 받아 이를 비교합니다.
이번에도 위와 비슷한 예제로 테스트를 한번 진행해보겠습니다.
public class Person implements Comparator<Person> {
private int age;
public Person(int age) {
this.age = age;
}
@Override
public int compare(Person o1, Person o2) {
if(o1.age - o2.age > 0){
return 1;
}else if(o1.age == o2.age){
return 0;
}else{
return -1;
}
}
...
}
똑같이 Person 클래스에 해당 인터페이스를 구현해줍니다.
그리고, person1과 person2를 비교하려고 하는데 compare 메서드의 매개변수는 o1과 o2이기 때문에 둘을 비교해줄 또 다른 Person 객체가 필요합니다. 두 객체를 비교하기 위해 사용하지도 않는 referee 객체를 만드는 것이 좀 불편합니다.
Comparable 인터페이스 예시에서처럼 Collections 클래스의 sort 메서드를 통해 비교해보려고 합니다.
위 예시는 Collections의 sort 메서드를 이용하여 List를 정렬시킨 것입니다. 이때, Person 클래스에 Comparator 인터페이스를 구현하지 않고 익명 객체를 사용하여 compare 메서드를 구현하여 정렬 조건을 만들 수 있습니다.
정리
위의 예시들처럼 Comparator 인터페이스는 익명 객체를 사용하여 개발자가 원하는 특수한 정렬을 구현할 수 있습니다.
그렇지만, Comparable 인터페이스는 한 번 클래스에 이를 구현해두면 이것이 default가 됩니다.
그렇기 때문에 Comparator 인터페이스는 정렬 조건이 여러개 필요할 때 사용하고, Comparable 인터페이스는 그 클래스의 기본 정렬을 정의하는 데 사용이 됩니다.