[Java/자바] Comparator와 Comparable

Comparable과 Comparator는 인터페이스로 실제 소스는 다음과 같습니다.

public interface comparable {
	public int compareTo(Object o1, Object o2);
}

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

인터페이스이기에 Comparable이나 Comparator을 사용하고자 한다면 인터페이스 내에 선언된 메소드를 반드시 구현해야합니다.

 

compareTo()와 compare()는 선언형태와 이름이 약간 다를 뿐 두 객체를 비교한다는 같은 기능을 목적으로 만들어졌습니다.

 

  • compareTo()

반환값은 int이지만, 실제로는 비교하는 두 객체가 같으면 0, 비교하는 값보다 작으면 음수, 크면 양수를 반환

 

  • compare()

두 객체를 비교해 음수, 0, 양수 중의 하나를 반환

 

 

Comparable : 기본 정렬기준(오름차순)을 구현하는데 사용
Comparator : 기본 정렬기준 외에 다른 기준으로 정렬하고자할 때 사용

사용 예제

import java.util.*;

class ComparatorEx {
	public static void main(String[] args) {
		
		/* Array String 배열 정렬 */
		String[] strArr = {"cat", "Dog", "lion", "tiger"};

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

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

		 // 역순 정렬 ( 내림차순 )
		Arrays.sort(strArr, new Descending());
		System.out.println("strArr 내림차순 =" + Arrays.toString(strArr));
		 
		Arrays.sort(strArr, Collections.reverseOrder());
		System.out.println("strArr 내림차순 =" + Arrays.toString(strArr));
		
		System.out.println("---------");
		/* Array int 배열 정렬 */
		int[] intArr = {3, 4, 5, 1, 7};
		Arrays.sort(intArr);
		System.out.println("intArr 오름차순 =" + Arrays.toString(intArr));
		
		Integer[] intArr2 = Arrays.stream(intArr).boxed().toArray(Integer[]::new);
		Arrays.sort(intArr2, Collections.reverseOrder());
		System.out.println("intArr 내림차순 =" + Arrays.toString(intArr2));
		
		System.out.println("---------");
		/* ArrayList 정렬 */
		List<String> list = new ArrayList<>();
		list.add("c");
		list.add("B");
		list.add("d");
		list.add("A");
		list.add("E");
		
		// 오름차순 정렬
		Collections.sort(list);
		System.out.println("list 오름차순 =" + list);
		
        // 대소문자 구분없이 오름차순        
        Collections.sort(list, String.CASE_INSENSITIVE_ORDER);        
        System.out.println("list 오름차순 (대소문자 구분X) =" + list);    
		
		// 내림차순 정렬
		Collections.sort(list, Collections.reverseOrder());
		System.out.println("list 내림차순 =" + list);
	
		
	}
}

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

 

이 예제에서  String.CASE_INSENSITIVE_ORDER문자열을 대소문자 구분없이 정렬하는 Comparator 입니다.

 

또한 여기서 String 타입일 때는 비교적 쉽게 Arrays.sort(strArr, Collections.reverseOrder()); 로 내림차순 정렬이 가능하지만,

int는 위와 같은 방법으로 정렬할 수 없고, Integer타입 배열로 변경해 주어야 합니다.

 

그리고 내림차순을 사용하기 위해 Comparator를 구현한 Descending 클래스가 있는데

이처럼 원하고자 하는 정렬을 사용하면 이런식으로 수정하여 정렬할 수 있습니다.

다만, compara()의 매개변수가 Object 타입이기 때문에 compareTo()를 호출할 수 없으므로

먼저 Comparable로 형변환해야 한다는 것에 주의합시다.

 


참고자료
자바의 정석3