Java - Comparable, Comparator로 정렬하기

Java 객체 정렬하기

Posted by Yan on August 7, 2021

Comparable Interface vs Comparator Interface

객체를 정렬한다는 것은 사용자가 정의한 기준으로 정렬하는 것이다.
객체를 비교하는 정렬 기준을 Comparable과 Comparator 인터페이스로 명시할 수 있다.
Comparable과 Comparator은 모두 인터페이스다.
인터페이스에 선언된 메소드를 구현하면서 사용자가 정렬 기준을 만든다는 것이다.

Interface Comparable

  • compareTo(T o)가 선언되어 있다. -> 이 메소드를 오버라이드해서 사용한다.
  • 자기 자신과 매개변수 객체를 비교한다.
  • java.lang 패키지 소속이다. import할 필요가 없다.

Comparable 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ClassName implements Comparable<Type> { 
 
/*
  ...
  code
  ...
 */
 
	// 필수 구현 부분
	@Override
	public int compareTo(Type o) {
		/*
		 비교 구현
		 */
	}
}

type에는 해당 클래스와 비교하고자하는 객체의 타입이 들어간다.

  • compareTo 메소드의 리턴값이
    • 양수일 때 : 자기자신이 비교대상 파라미터보다 크다
    • 0 일 때 : 동일하다
    • 음수일 때 : 자기자신이 비교대상 파라미터보다 작다
  • 따라서 메소드를 구현할 때

Comparable를 이용해 정렬한 예시 코드

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Sort10825 {
    static StringBuilder sb = new StringBuilder();
    static FastReader scan = new FastReader();

    static class Elem implements Comparable<Elem> {

        public String name;
        public int korean, english, math;

        @Override
        public int compareTo(Elem other) {
            if (korean != other.korean) return other.korean - korean;
            if (english != other.english) return english - other.english;
            if (math != other.math) return other.math - math;
            return name.compareTo(other.name);
        }
    }

    static int N;
    static Elem[] a;

    static void input() {
        N = scan.nextInt();
        a = new Elem[N];
        for (int i = 0; i < N; i++) {
            a[i] = new Elem();
            a[i].name = scan.next();
            a[i].korean = scan.nextInt();
            a[i].english = scan.nextInt();
            a[i].math = scan.nextInt();
        }
    }

    static void pro() {
        Arrays.sort(a);
        for (int i = 0; i < N; i++) {
            sb.append(a[i].name).append('\n');
        }
        System.out.println(sb.toString());
    }

    public static void main(String[] args) {
        input();
        pro();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public FastReader(String s) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(new File(s)));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

여기서

1
2
3
4
5
6
7
8
9
10
11
12
13
    static class Elem implements Comparable<Elem> {

        public String name;
        public int korean, english, math;

        @Override
        public int compareTo(Elem other) {
            if (korean != other.korean) return other.korean - korean;
            if (english != other.english) return english - other.english;
            if (math != other.math) return other.math - math;
            return name.compareTo(other.name);
        }
    }

이 부분이 Comparable을 상속하고 있다.

Interface Comparator

  • compare(T o1, T o2)가 선언되어있다. -> 이 메소드를 오버라이드해서 사용한다.
  • 두 매개변수 객체를 비교한다. 자기 자신과 상관없이 파라미터로 들어오는 두 객체를 비교햔다.
  • java.util 패키지 소속이다.

Comparator 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.Comparator;	// import 필요
public class ClassName implements Comparator<Type> { 
 
/*
  ...
  code
  ...
 */
 
	// 필수 구현 부분
	@Override
	public int compare(Type o1, Type o2) {
		/*
		 비교 구현
		 */
	}
}

Comparator를 이용해 정렬한 예시 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.Comparator;

public class Ex {
    public static void main(String[] args) {

        public static Comparator<Cat> comp1 = new Comparator<Cat>() {
            @Override
            public int compare(Cat o1, Cat o2) {
                return o1.age - o2.age;
            }
        }
    };
}

class Cat {

    int age;
    int weight;

    Cat(int age, int weight) {
        this.age = age;
        this.weight = weight;
    }
}

이 부분이 익명객체를 활용한 부분이다.

  • 익명객체 : 이름이 정의되지 않은 객체
  • 익명객체는 보통 인스턴스를 생성할 때 Cat c = new Cat();라고 쓰는 것과 달리 Cat c = new Cat(){구현부};로 쓴다.
  • comp1 익명객체는 Ex를 상속받은 하나의 새로운 클래스를 만든 것이다.

reference

[Java] Comparable와 Comparator의 차이와 사용법
자바 [JAVA] - Comparable 과 Comparator의 이해