Comparator 와 Comparable 의 차이 - 객체 내부 비교와 외부 비교 관점
Comparator와 Comparable 이란 뭘까?
둘 다 인터페이스로 컬렉션을 정렬하는데 필요한 메서드를 정의하고 있다.
- Comparable
Comparable 을 구현하고 있는 클래스들은 같은 타입의 인스턴스끼리 서로 비교할 수 있는 클래스들을 의미하며 주로 Integer와 같은 wrapper 클래스와 String, Date, File과 같은 것들을 말한다. 기본적으로 오름차순으로 구현되어 있다.
아래 소스는 실제로 java.lang 라이브러리에 있는 Integer, String 같은 클래스를 확인해본 것이다. 각각 기준에 맞게 Comparable interface를 구현해서 사용하고 있다.
// Integer
public final class Integer extends Number
implements Comparable<Integer>, Constable, ConstantDesc {
}
// string
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence,
Constable, ConstantDesc {
Comparable의 내용은 다음과 같다.
public interface Comparable<T> {
/**
* Compares this object with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.
*
* <p>The implementor must ensure {@link Integer#signum
* signum}{@code (x.compareTo(y)) == -signum(y.compareTo(x))} for
* all {@code x} and {@code y}. (This implies that {@code
* x.compareTo(y)} must throw an exception if and only if {@code
* y.compareTo(x)} throws an exception.)
*
* <p>The implementor must also ensure that the relation is transitive:
* {@code (x.compareTo(y) > 0 && y.compareTo(z) > 0)} implies
* {@code x.compareTo(z) > 0}.
*
* <p>Finally, the implementor must ensure that {@code
* x.compareTo(y)==0} implies that {@code signum(x.compareTo(z))
* == signum(y.compareTo(z))}, for all {@code z}.
*
* @apiNote
* It is strongly recommended, but <i>not</i> strictly required that
* {@code (x.compareTo(y)==0) == (x.equals(y))}. Generally speaking, any
* class that implements the {@code Comparable} interface and violates
* this condition should clearly indicate this fact. The recommended
* language is "Note: this class has a natural ordering that is
* inconsistent with equals."
*
* @param o the object to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*
* @throws NullPointerException if the specified object is null
* @throws ClassCastException if the specified object's type prevents it
* from being compared to this object.
*/
public int compareTo(T o);
}
같은 맥락에서 Arrays.sort() 를 호출하면 컴퓨터가 알아서 배열을 정렬해 주는 것이 아니라, 사실은 내부적으로 Comparable 인터페이스를 구현함으로써 정렬되고 있는 것이다. 이와 같이 Comparable 은 일반적으로 기본정렬 기준을 구현하는데 사용한다.
여기서 기본정렬 기준이란, Comparable 인터페이스를 통해 구현한 객체 자체가 기준이 되는 것을 말한다. 예를 들어, Integer, String와 같은 객체는 내부에서 정의된 compareTo 메서드에 의해 정렬이 된다. 즉 객체 자체의 내부 정의 ( compareTo )에 의해 정렬되는 것을 의미하는 것이다.
- Comparator
Comparator 도 Comparable 과 동일하게 두 객체를 비교하기 위해 고안된 인터페이스이다. 기본 정렬기준 외에 다른 기준으로 정렬하고자 할 때 사용한다. 즉, 객체가 가진 내부 정렬 외에, 다른 조건으로 정렬할 때 Comparator을 사용할 수 있다.
@FunctionalInterface
public interface Comparator<T> {
/**
* Compares its two arguments for order. Returns a negative integer,
* zero, or a positive integer as the first argument is less than, equal
* to, or greater than the second.<p>
*
* The implementor must ensure that {@link Integer#signum
* signum}{@code (compare(x, y)) == -signum(compare(y, x))} for
* all {@code x} and {@code y}. (This implies that {@code
* compare(x, y)} must throw an exception if and only if {@code
* compare(y, x)} throws an exception.)<p>
*
* The implementor must also ensure that the relation is transitive:
* {@code ((compare(x, y)>0) && (compare(y, z)>0))} implies
* {@code compare(x, z)>0}.<p>
*
* Finally, the implementor must ensure that {@code compare(x,
* y)==0} implies that {@code signum(compare(x,
* z))==signum(compare(y, z))} for all {@code z}.
*
* @apiNote
* It is generally the case, but <i>not</i> strictly required that
* {@code (compare(x, y)==0) == (x.equals(y))}. Generally speaking,
* any comparator that violates this condition should clearly indicate
* this fact. The recommended language is "Note: this comparator
* imposes orderings that are inconsistent with equals."
*
* @param o1 the first object to be compared.
* @param o2 the second object to be compared.
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
*/
int compare(T o1, T o2);
- int compare(Object o) 과 int compareTo(Object o1, Object o2)
두 객체를 비교하려는 목적으로 고안 되었으며 비교하는 두 객체가 같으면 0, 비교하는 값 보다 작으면 음수, 크면 양수를 반환한다.