Comparable과 Comparator

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

→ 정렬: 오름차순, 내림차순, 나이를 기준으로 정렬, 키를 기준으로 정렬, ...

  • Comparable: 기본 정렬기준(default)을 구현하는 데 사용
    → 객체(o)와 자신(this)을 비교
  • Comparator: 기본 정렬기준(default) 외에 다른 기준으로 정렬하고자 할 때 사용
    • 0: 같다 (o1 = o2)
    • 양수: 왼쪽이 크다 (o1 > o2)
    • 음수: 오른쪽이 크다 (o1 < o2)
1
2
3
4
5
6
7
8
public interface Comparable {
    int compareTo(Object o); //주어진 객체(o)를 자신(this)과 비교
}
 
public interface Comparator {
    int compare(Object o1, Object o2); //o1, o2 두 객체를 비교
    boolean equals(Object obj); //equals를 오버라이딩하라는 뜻
}
cs
  • compare()와 compareTo()는 두 객체의 비교결과를 반환하도록 작성
    같으면 0, 오른쪽이 크면 음수(-), 작으면 양수(+)
1
2
3
4
5
6
7
8
9
10
11
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));
    }
    ...
 
}
cs

 

자리바꿈
  • 오름차순: 7 > 5 => 5, 6, 7, 8, ...
  • 내림차순: 5 < 7 => 7, 6, 5, 4, ...
정렬
  1. 정렬 대상 ex) strArr
  2. 정렬 기준 ex)String.CASE_INSENSITIVE_ORDER (대소문자 구분X) / new Descending() (역순 정렬)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Ex11_7 {
 
    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); //정렬대상, 정렬기준(대소문자 구분X)
        System.out.println("strArr= " + Arrays.toString(strArr));
        
        Arrays.sort(strArr, new Descending()); //역순 정렬
        System.out.println("strArr= " + Arrays.toString(strArr));
    }
 
}
 
class Descending implements Comparator {
 
    @Override
    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;
    }
 
}
cs

실행 결과


Integer와 Comparable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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을 반환한다.
        return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
 
        //오른쪽 값이 크면 음수를, 두 값이 같으면 0, 왼쪽 값이 크면 양수를 반환한다.
        return thisVal - anotherVal; //내림차순의 경우 반대로 뺄셈하면 된다.
    }
        ...
}
 
cs

 


Comparable의 compareTo 사용해보기

예제) 좌표 정렬하기

N개의 평면상의 좌표(x, y)가 주어지면 모든 좌표를 내림차순으로 정렬하는 프로그램을 작성하세요.
[입력]
첫째 줄에 좌표의 개수인 N(3<=N<=100,000)이 주어진다.
두 번째 줄부터 N개의 좌표가 x, y 순으로 주어진다. x, y 값은 양수만 입력된다.
[출력]
N개의 좌표를 정렬하여 출력하세요.
[예시]
아래 이미지 참조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package day02;
 
import java.util.*;
 
public class Q17_PointSort {
 
    public static void main(String[] args) {
        //x, y좌표를 갖는 Point 클래스를 구현하여 정렬하세요
        //우선 x좌표를 내림차순 정렬하되, x값이 동일할 경우는 y값 내림차순으로 정렬하세요
        Scanner scanner = new Scanner(System.in);
        System.out.println("좌표의 개수를 입력하세요: ");
        int num = scanner.nextInt();
        ArrayList<Point> arr = new ArrayList<>(); //Point 객체를 담을 ArrayList
        System.out.println("좌표(x, y)의 x, y값을 입력하세요: ");
        for(int i = 0; i < num; i++) {
            int x = scanner.nextInt();
            int y = scanner.nextInt();
            arr.add(new Point(x, y)); //ArrayList에 Point 객체를 생성하여 담기
        }
        
        //override한 compareTo의 정렬 기준에 따라 sort가 자동으로 정렬해준다.
        Collections.sort(arr);
        for(Point o:arr) {
            System.out.println(o.getX() + " " + o.getY());
        }
    }
 
}
 
class Point implements Comparable<Point>{
    private int x;
    private int y;
    
    public Point() {
        
    }
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int getX() {
        return x;
    }
    
    public int getY() {
        return y;
    }
    
    @Override
    public int compareTo(Point o) {
        if(this.x == o.x) { //x좌표의 값이 같으면 y좌표의 값으로 정렬
            return o.y - this.y; //y좌표 내림차순
        }else {
            return o.x - this.x; //그 외 x좌표 내림차순
        }
    }
    
}
cs

 

compareTo() 메서드는 개발자가 직접 호출하는 게 아니라 Comparable 인터페이스가 구현된 클래스 객체들이 담겨 있는 배열을 .sort()시 자동으로 호출되면서 각각의 객체들의 비교를 수행한다.

실행 결과

 

+ Recent posts