스터디/JAVA

Comparable과 Comparator는 언제 써야할까?

Big Sun 2023. 6. 1. 11:24
728x90

 

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이 앞에 위치한 것을 확인할 수 있습니다.

Collections 클래스의 sort 메서드

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 메서드

 

 

 

위 예시는 Collections의 sort 메서드를 이용하여 List를 정렬시킨 것입니다. 이때, Person 클래스에 Comparator 인터페이스를 구현하지 않고 익명 객체를 사용하여 compare 메서드를 구현하여 정렬 조건을 만들 수 있습니다.



정리

 

위의 예시들처럼 Comparator 인터페이스는 익명 객체를 사용하여 개발자가 원하는 특수한 정렬을 구현할 수 있습니다.

그렇지만, Comparable 인터페이스는 한 번 클래스에 이를 구현해두면 이것이 default가 됩니다.

그렇기 때문에 Comparator 인터페이스는 정렬 조건이 여러개 필요할 때 사용하고, Comparable 인터페이스는 그 클래스의 기본 정렬을 정의하는 데 사용이 됩니다.

 

 

 

 

728x90