elevne's Study Note

Java의정석 공부 - (6: Comparator/Comparable) 본문

Backend/Java

Java의정석 공부 - (6: Comparator/Comparable)

elevne 2023. 2. 4. 11:27

ComparatorComparable 은 모두 인터페이스로, 객체들을 정렬 또는 Binary Search Tree 를 구성하는데 필요한 메서드를 정의한다.

 

 

Comparable 을 구현하고 있는 클래스들은 같은 타입의 인스턴스끼리 서로 비교할 수 있는 클래스들, 주로 Integer 과 같은 wrapper 클래스 (Boolean 제외) 와 String, Date, File 과 같은 것들이며 기본적으로 오름차순으로 정렬되도록 구현되어 있다. 즉, Comparable 을 구현한 클래스는 정렬이 가능하다는 것이다. 이전 Collection framework 에서 알아보았던 TreeSet 또한 Comparable 을 구현한 내용에 따라서 자료들이 정렬되는 것이다. 만약 Comparable 을 구현하지 않은 클래스의 인스턴스를 TreeSet 에 담게 된다면 정렬기준이 없기 때문에 정렬되지 않고 실행 시 에러가 발생하게 된다.

 

 

Comparable기본 정렬기준을 구현하는데 사용하는 것이고, Comparator 은 기본 정렬기준 외에 다른 기준으로 정렬하고자할 때 사용한다. Comparable 을 구현한 클래스들은 기본적으로 오름차순으로 정렬되는데, 이 때 내림차순 혹은 다른 기준에 의해 정렬되도록 하고 싶을 때 Comparator 을 구현해서 정렬기준을 제공할 수 있는 것이다.

 

 

 

아래 코드 예는 Comparable 인터페이스를 implement 한 Integer wrapper 클래스이다.

 

 

 

    /**
     * Compares two {@code Integer} objects numerically.
     *
     * @param   anotherInteger   the {@code Integer} to be compared.
     * @return  the value {@code 0} if this {@code Integer} is
     *          equal to the argument {@code Integer}; a value less than
     *          {@code 0} if this {@code Integer} is numerically less
     *          than the argument {@code Integer}; and a value greater
     *          than {@code 0} if this {@code Integer} is numerically
     *           greater than the argument {@code Integer} (signed
     *           comparison).
     * @since   1.2
     */
    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }

    /**
     * Compares two {@code int} values numerically.
     * The value returned is identical to what would be returned by:
     * <pre>
     *    Integer.valueOf(x).compareTo(Integer.valueOf(y))
     * </pre>
     *
     * @param  x the first {@code int} to compare
     * @param  y the second {@code int} to compare
     * @return the value {@code 0} if {@code x == y};
     *         a value less than {@code 0} if {@code x < y}; and
     *         a value greater than {@code 0} if {@code x > y}
     * @since 1.7
     */
    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

 

 

 

클래스 내부에 Comparable 의 compareTo(T o) 메서드를 구현해놓은 것을 볼 수 있다. (TreeSet 에 Integer 인스턴스들을 저장했을 때 정렬되는 기준이 이 compareTo 메서드에 의한 것이다)

 

 

 

아래와 같이 Comparator 과 Comparable 을 사용하여 나만의 정렬기준으로 정렬시킬 수도 있다.

 

 

 

class Descending implements Comparator {
    public int compare(Object o1, Object o2) {
        if (o1 instanceof Comparable && o2 instanceof Comparable) {
            Comparable c1 = (Comparable) o1;
            Comparable c2 = (Comparable) o2;
            return c1.compareTo(c2) * -1;
        }
        return -1;
    }
}
public class Main {
    public static void main(String[] args){
        TreeSet set1 = new TreeSet();
        TreeSet set2 = new TreeSet(new Descending());
        int[] scores = {30, 50, 10 ,20, 40};
        for (int i = 0; i < scores.length; i++){
            set1.add(new Integer(scores[i]));
            set2.add(new Integer(scores[i]));
        }
        System.out.println("set1: "+set1);
        System.out.println("set2: "+set2);
    }
}

 

 

result

 

 

 

TreeSet 은 데이터를 정렬된 상태로 저장하는데, 이 때 따로 Comparator 을 지정해주면 해당 객체에 구현된 정렬방식에 따라서 정렬하여 저장하게 된다. 

 

 

 

 

 

 

Reference:

자바의 정석