Arrays.sort(), Comparable, Comparator

2022. 4. 13. 23:21개발공부/Java

Arrays.sort(), Comparable, Comparator

Sort

Java에서 Collections나 Arrays를 정렬하기 위해 sort() 를 사용합니다.
Sorting 알고리즘은 퀵 정렬을 채택해 시간복잡도는 O(nlong(n)) 입니다. 타입이 객체거나 2차원 배열을 사용해서 sorting해줄 땐 Comparator를 파라미터에 추가해줘야 합니다.

Comparable

compareTo() 메서드만 가지고 있는 인터페이스 입니다. Integer, Long, Date 등의 타입클래스는 Comparable를 상속해 compareTo()가 오버라이딩 되어 있습니다.
만일 내가 클래스를 따로 만들어 Comparable를 상속하고, compareTo()오버라이딩 한다면 Sort할 때 오버라이딩으로 구현해준 메서드를 통해 정렬할 수 있습니다.

public final class Integer extends Number implements Comparable<Integer> {
    //...
    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
}

public class Date implements java.io.Serializable, Cloneable, Comparable<Date> {
    //...
    public int compareTo(Date anotherDate) {
        long thisTime = getMillisOf(this);
        long anotherTime = getMillisOf(anotherDate);
        return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1));
    }
}

public final class Long extends Number implements Comparable<Long> {
    //...
    public int compareTo(Long anotherLong) {
        return compare(this.value, anotherLong.value);
    }
}

Comparator

Comparator는 functional interface라서 하나의 추상 메서드comare(T o1, T o2)를 가지며, 여러 개의 이미 구현되어 있는 default 메서드를 가집니다.
그 중에서 Sorting에서 자주 사용되는 건 comparing() 입니다. 파라미터로 Function<? super T, ? extends U> keyExtractor을 가집니다.
keyExtractor는 Sorting때 비교대상이 되는 값을 extract 하는 함수를 말합니다.(e.g (o1, o2) -> { ... }, o1 -> o1[0])


    public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

comparing()Comparable 인터페이스의 compareTo() 메서드를 호출하는데, 두 값(x,y) 을 비교해서 x > y => 1, x == y => 0, x < y => -1 을 반환합니다. 리턴된 값으로 sorting이 진행됩니다.

결론

ComparableComparator 인터페이스는 값을 비교해 return 해주는 동일한 기능을 하지만, 다양한 메서드를 보유한 funcational interface Comparator 인터페이스는 Collections, Arrays의 sort() 메서드에서 파라미터로 받고 있기 때문에
람다형으로 표현이 가능하기 때문에 특성을 알아두고 잘 사용하면 좋을 것 같습니다.