JAVA

[Collections Framework] Comparator, Comparable

ewok 2023. 2. 24. 17:36

객체 정렬에 필요한 메서드(정렬기준 제공)를 정의한 인터페이스

 

Comparable

기본 정렬기준을 구현하는데 사용

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

주어진 객체 o를 자신(this)과 비교

 

Comparator

기본 정렬기준 외에 다른 기준으로 정렬하고자 할 때 사용

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

o1, o2 두 객체를 비교하여 정수값으로 반환한다. 0이면 같은 값, 양수이면 왼쪽이 크고, 음수이면 오른쪽이 큰 값이다.

equals를 오버라이딩 한다.

 

 

sort()는 두 대상을 비교하여 자리를 바꾸는 것을 반복하는 것이다.

 

 

compare()와 compareTo()는 두 객체의 비교 결과를 반환하도록 작성한다.

public final class Integer extends Number implements comparable {
	public int compareTo(Integer anotherInteger) {
            int v1 = this.value;
            int v2 = anotherInteger.value;

            // 같으면 0, 오른쪽 값이 크면 -1(음수), 작으면 1(양수)을 반환
            return (v1 < v2 ? -1 : (v1==v2? 0 : 1));
    	}
}

삼항연산자를 사용하지 않고 v1-v2(뺄셈)를 해도 되는데 성능을 위해 삼항연산자를 사용한다. (보통 삼항연산자가 조금 더 빠르다.)

 

import java.util.*;

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));
	}
}

// 기본정렬 기준이 아닌 새로운 정렬 기준을 주려먼 Comparator 인터페이스를 구현해야 한다.
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;
	} 
}

 

 

정렬을 하기 위해서는 정렬 방법과 기준이 필요하다. 정렬 방법은 선택, 삽입, 버블, 퀵 등 고정적이다. 반면 정렬 기준은 가변적이다. 따라서 정렬 방법은 존재하는 방법을 사용하면 되고 기준만 필요할 때 정해주면 된다.

 

아래는 버블 정렬의 코드이다.

static void sort(int[] intArr) {
    for(int i=0; i<intArr.length-1; i++ {
        for(int j=0; j<intArr.length-1; j++{
            int tmp = 0;

            // 정렬기준
            if(intArr[j] > intArr[j+1]) { // 가변
                //자리바꿈
                tmp = intArr[j];
                intArr[j] = intArr[j+1];
                intArr[j+1] = tmp;
            }
        }
    }
}

정렬 기준은 오름차순, 내림차순, 성적순, 이름순, 가나다 순 등등 상황에 따라 바뀐다. 반면 정렬 방법은 바뀌지 않는다.

 

static void sort(Object[] objArr, Comparator c) {
    for(int i=0; i<objArr.length-1; i++ {
        for(int j=0; j<objArr.length-1; 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;
            }
        }
    }
}

여기서 정렬방법의 코드는 변경 없이 비교 기준만 매개변수로 받아오면 된다.