코린이의 소소한 공부노트

Comparator, Comparable 인터페이스 본문

Java

Comparator, Comparable 인터페이스

무지맘 2022. 11. 5. 00:41

[객체 정렬 인터페이스]

객체를 정렬할 때는 정렬 대상과 정렬 기준이 필요하다. 이때 객체 정렬에 필요한 메서드(정렬 기준 제공)를 정의한 인터페이스가 바로 컴페러터와 컴페어러블이다.

// Comparable 기본 정렬 기준을 구현하는데 사용
public interface Comparable{
    int compareTo(Object o); // o와 자신(this)을 비교
}

// Comparator 기본 정렬 기준 외에 다른 기준으로 정렬하고자 할 때 사용
public interface Comparator{
    int compare(Object o1, Object o2); // o1과 o2를 비교. o1이 크면 1, 같으면 0, 작으면 –1 반환
    boolean equals(Object obj); // 오버라이딩
}

 

[Integer Comparable]

compare()compareTo()는 두 객체의 비교 결과를 반환하도록 작성되어 있다. 객체 비교의 가장 기본이 되는 숫자, 그중에서 Integer 클래스의 코드를 살펴보겠다.

public final class Integer extends Number implements Comparable{
    ...
    public int compareTo(Object o){
        return compareTo((Integer)o);
    }
 
    public int compareTo(Integer anotherInteger){
        int v1 = this.value;
        int v2 = anotherInteger.value;
        return (v1 < v2 ? -1 : (v1==v2 ? 0 : 1));
        // 매개변수가 크면 –1, 같으면 0, 작으면 1 반환
        // return v1 – v2; 와 같음
        // 뺄셈보다 비교가 성능이 약간 더 좋음
        // 뺄셈은 끝 bit까지 계산해야하지만, 비교는 앞에서부터 비교해서 다르면 결과가 바로 나오기 때문
    }
    ...
}

 

[객체 비교 사용 예시]

String[] arr = {"cat", "Dog", "lion", "tiger"};

// static void sort(Object[] a) 객체 배열에 저장된 객체가 구현한 Comparable에 의한 정렬
Arrays.sort(arr); // String의 Comparable구현에 의한 정렬
System.out.println("strArr=" + Arrays.toString(arr)); // strArr=[Dog, cat, lion, tiger]
// 대소문자 구분시 대문자가 앞이다.

Arrays.sort(arr, String.CASE_INSENSITIVE_ORDER); // 대소문자 구분안함
System.out.println("strArr=" + Arrays.toString(arr)); // strArr=[cat, Dog, lion, tiger]

Arrays.sort(arr, new Descending()); // 새로 만든 역순 정렬
System.out.println("strArr=" + Arrays.toString(arr)); // strArr=[tiger, lion, cat, Dog]

// 새로 만든 역순 정렬 클래스
class Descending implements Comparator { // 새로운 정렬기준이므로 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; // 비교할 수 없는 객체일 때 -1 반환
    }
}

[쿠키글] 매개변수로 정렬 방식(logic)은 왜 받지 않는 걸까?

정렬을 할 때는 두 대상을 비교하고 정렬 기준에 부합하면 자리를 바꾸는 일을 반복적으로 수행한다. 그렇기 때문에 정렬 방식은 변함이 없고, 다만 정렬 대상과 기준은 계속 바뀌기 때문에 매개변수로 받는 것이다.

static void sort(Object[] objArr, Comparator c){ // 정렬 대상 + 기준
    for(int i=0 ; i<objArr.length ; i++){
        for(int j=0 ; j<objArr.length ; j++){
            Object tmp = null;
            if(c.compare(objArr[j], objArr[j+1])>0){ // 정렬 기준이 적용되는 코드
                tmp = objArr[j];
                objArr[j] = objArr[j+1];
                objArr[j+1] = tmp;
            }
        } // for j
    } // for i
}

'Java' 카테고리의 다른 글

TreeSet 클래스  (0) 2022.11.07
HashSet 클래스  (0) 2022.11.07
Arrays 클래스  (0) 2022.11.04
Iterator, ListIterator, Enumeration 인터페이스  (0) 2022.11.03
스택 클래스와 큐 인터페이스  (0) 2022.11.02