3 minute read

Comparable Interface vs Comparator Interface

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

Interface Comparable

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

Comparable 코드

public class ClassName implements Comparable<Type> { 
 
/*
  ...
  code
  ...
 */
 
	// 필수 구현 부분
	@Override
	public int compareTo(Type o) {
		/*
		 비교 구현
		 */
	}
}

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

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

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

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

여기서

    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 코드

import java.util.Comparator;	// import 필요
public class ClassName implements Comparator<Type> { 
 
/*
  ...
  code
  ...
 */
 
	// 필수 구현 부분
	@Override
	public int compare(Type o1, Type o2) {
		/*
		 비교 구현
		 */
	}
}

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

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의 이해

Comments