본문 바로가기
DEV/Java

[자바] Comparator 와 Comparable

by 어쩌다개발 2023. 2. 14.
반응형

Arrays.sort()를 호출하면 컴퓨터가 알아서 배열을 정렬하는 것처럼 보이지만 사실 Character 클래스의 Comparable의 구현에 의해 정렬되었던 것이다. Comparator 와 Comparable은 모두 인터페이스로 컬렉션을 정렬하는데 필요한 메서드를 정의하고 있으며, Comparable 을 구현하고 있는 클래스들은 같은 타입의 인스턴스끼리 서로 비교할 수 있는 클래스들, 주로 Integer와 같은 wrapper 클래스와 String, Date, File 과 같은 것들이다.

기본적으로 오름차순(작은 -> 큰)으로 정렬되도록 구현되어 있다.

즉, Comparable을 구현한 클래스는 정렬이 가능하다는 것을 의미한다.

public interface Comparator {
	int compare(Object o1, Object o2);
    boolean equals(Object obj);
}

public interface Comparable {
	public int compareTo(Object o);
}

Comparable은 java.lang 패키지에 있고, Comparator는 java.util 패키지에 있다.

compare()와 compareTo()는 선언형태와 이름이 약간 다를 뿐 두 객체를 비교한다는 같은 기능을 목적으로 고안된 것이다.

CompareTo()는 반환값이 int지만 실제로는 비교하는 두 객체가 같으면 0, 비교하는 값보다 작으면 음수, 크면 양수를 반환하도록 구현해야 한다. 이와 마찬가지로 compare()도 객체를 비교해서 음수, 0 , 양수 중의 하나를 반환하도록 구현해야 한다.

equals 메서드는 모든 클래스가 가지고 있는 공통적인 메서드지만, Comparator를 구현하는 클래스는 오버라이딩이 필요할 수도 있다는 것을 알리기 위해서 정의한 것일 뿐, 그냥 compare(Object o1, Object o2)만 구현하면 된다.

public final class Integer extends Number implements Comparable {
	...
    public int compareTo(Object o) {
    	return compareTo((Integer) o);
    }
    
    public int compareTo(Integer anotherInteger) {
    	int thisVal = this.value;
        int anotherVal = anotherInteger.value;
        
        //비교하는 값이 크면 -1, 같으면 0, 작으면 1을 반환
        reuturn (thisVal < anotherVla ? -1 : (thisVal == anotherVal ? 0 : 1));
    }
}

위 코드는 Integer 클래스 일부인데 Comparable의 compareTo(Object o)를 구현해놓을것을 볼 수 있다.

Comparable을 구현한 클래스들이 기본적으로 오름차순으로 정렬되어 있지만, 내림차순으로 정렬한다던가 다른 기준에 의해서 정렬되게 하고 싶을 때는 Comparator를 구현해서 정렬기준을 제공할 수 있다.

Comparable 기본 정렬기준을 구현하는데 사용
Comparator 기본 정렬기준 외에 다른 기준으로 정렬하고자 할 때 사용
import java.util.Arrays;
import java.util.Comparator;

public class ComparatorEx {
    public static void main(String[] args) {
        String[] strArr = {"cat", "Dog", "lion", "tiger"};

        Arrays.sort(strArr); //String의 Comparable 구현에 의한 정렬
        System.out.println("strArr = " + Arrays.toString(strArr));

        Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER); //대소문자 구분 안함
        System.out.println("strArr = " + Arrays.toString(strArr));

        Arrays.sort(strArr, new Descending()); //역순정렬
        System.out.println("strArr = " + Arrays.toString(strArr));
    }
}

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;
            //-1을 곱해서 정렬 방식을 역으로 변경
            // c2.compareTo(c1)으로 순서 변경도 가능
        }
        return -1;
    }
}

 

 

참고: 자바의 정석

반응형

'DEV > Java' 카테고리의 다른 글

[자바] HashMap  (3) 2023.02.15
[자바] HashSet  (7) 2023.02.15
[자바] Arrays  (7) 2023.02.14
[자바] Stack(스택)과 Queue(큐)  (3) 2023.02.12
[자바] LinkedList  (3) 2023.02.11

댓글