자바에서 객체를 정렬하려면 Comparable 또는 Comparator 인터페이스를 사용해야 합니다. 두 인터페이스는 각각 compareTo()와 compare() 메서드를 제공하며, 용도와 사용 방식이 서로 다릅니다. 이 글에서는 두 메서드의 차이점을 예제 코드와 함께 자세히 살펴봅니다.
Comparable과 Comparator의 기본 개념
Comparable 인터페이스는 객체 정렬을 위한 compareTo() 메서드를 제공합니다. 이 방식으로 결정되는 순서를 해당 클래스의 기본 정렬(natural ordering)이라고 하며, compareTo() 메서드는 기본 비교 메서드(natural comparison method)라고 부릅니다.
반면 Comparator 인터페이스는 정렬 작업을 위한 compare() 메서드를 제공합니다. Comparator를 활용하면 여러 가지 정렬 기준(다중 정렬 시퀀스)을 만들 수 있어, 하나의 객체를 나이·이름·학번 등 서로 다른 데이터 멤버를 기준으로 각각 정렬할 수 있습니다.
compareTo() 메서드
compareTo() 메서드는 현재 객체(this)와 매개변수로 전달된 객체 o1을 비교한 결과를 정수로 반환합니다.
문법
public int compareTo(Object o1)
- 현재 객체가 o1보다 작은 경우에만 음수(-)를 반환합니다.
- 현재 객체가 o1보다 큰 경우에만 양수(+)를 반환합니다.
- 현재 객체가 o1과 같은 경우에만 0을 반환합니다.
예제
import java.util.*;
class Employee implements Comparable<Employee> {
String name;
int age;
Employee(String name, int age) {
this.name = name;
this.age = age;
}
// compareTo 메서드 오버라이드
@Override
public int compareTo(Employee o) {
return Integer.compare(this.age, o.age);
}
}
public class ComparableDemo {
public static void main(String[] args) {
// 생성
List<Employee> list = new ArrayList<>();
// 삽입
list.add(new Employee("Krishna", 30));
list.add(new Employee("Archana", 28));
list.add(new Employee("Vineet", 25));
list.add(new Employee("Ramesh", 38));
list.add(new Employee("Alok", 28));
System.out.println("Before sorting:");
for (Employee e : list) {
System.out.print("[ EMP : age = " + e.age + " ] ");
}
// 정렬
Collections.sort(list);
System.out.println("\nAfter sorting:");
for (Employee e : list) {
System.out.print("[ EMP : age = " + e.age + " ] ");
}
}
}
실행 결과
Before sorting: [ EMP : age = 30 ] [ EMP : age = 28 ] [ EMP : age = 25 ] [ EMP : age = 38 ] [ EMP : age = 28 ] After sorting: [ EMP : age = 25 ] [ EMP : age = 28 ] [ EMP : age = 28 ] [ EMP : age = 30 ] [ EMP : age = 38 ]
나이(age)를 기준으로 오름차순 정렬된 것을 확인할 수 있습니다. 참고로 두 정수의 차(this.age - o.age)를 반환하는 방식도 널리 쓰이지만, 값의 범위가 클 경우 오버플로우가 발생할 수 있으므로 Integer.compare()를 사용하는 것이 더 안전합니다.
compare() 메서드
compare() 메서드는 첫 번째 객체와 두 번째 객체를 비교하여 그 결과를 정수로 반환합니다.
문법
public int compare(Object o1, Object o2)
- o1이 o2보다 작은 경우에만 음수(-)를 반환합니다.
- o1이 o2보다 큰 경우에만 양수(+)를 반환합니다.
- o1이 o2와 같은 경우에만 0을 반환합니다.
예제
import java.util.*;
class Student {
String name;
int age, roll;
Student(String name, int age, int roll) {
this.name = name;
this.age = age;
this.roll = roll;
}
}
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return Integer.compare(s1.age, s2.age);
}
}
class RollComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return Integer.compare(s1.roll, s2.roll);
}
}
public class ComparatorDemo {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student("Ramesh", 30, 20));
list.add(new Student("Adithya", 7, 10));
list.add(new Student("Krishna", 25, 5));
list.add(new Student("Vineet", 24, 15));
System.out.println("BEFORE SORTING");
for (Student e : list) {
System.out.println("[ STU : name = " + e.name + " age = " + e.age + " roll = " + e.roll + "]");
}
Collections.sort(list, new AgeComparator());
System.out.println("AFTER SORTING WITH AGE");
for (Student e : list) {
System.out.println("[ STU : name = " + e.name + " age = " + e.age + " ]");
}
Collections.sort(list, new RollComparator());
System.out.println("AFTER SORTING WITH ROLL");
for (Student e : list) {
System.out.println("[ STU : name = " + e.name + " roll = " + e.roll + " ]");
}
}
}
실행 결과
BEFORE SORTING [ STU : name = Ramesh age = 30 roll = 20 ] [ STU : name = Adithya age = 7 roll = 10 ] [ STU : name = Krishna age = 25 roll = 5 ] [ STU : name = Vineet age = 24 roll = 15 ] AFTER SORTING WITH AGE [ STU : name = Adithya age = 7 ] [ STU : name = Vineet age = 24 ] [ STU : name = Krishna age = 25 ] [ STU : name = Ramesh age = 30 ] AFTER SORTING WITH ROLL [ STU : name = Krishna roll = 5 ] [ STU : name = Adithya roll = 10 ] [ STU : name = Vineet roll = 15 ] [ STU : name = Ramesh roll = 20 ]
같은 학생 목록이라도 AgeComparator를 적용하면 나이순으로, RollComparator를 적용하면 학번순으로 정렬됩니다. 이것이 Comparator의 강력한 장점입니다.
두 메서드의 핵심 차이점 요약
| 구분 | compareTo() | compare() |
|---|---|---|
| 소속 인터페이스 | java.lang.Comparable | java.util.Comparator |
| 매개변수 | 객체 1개 (this와 비교) | 객체 2개 |
| 정렬 기준 | 클래스당 하나의 기본 정렬만 정의 가능 | 여러 개의 정렬 기준을 자유롭게 정의 가능 |
| 클래스 수정 여부 | 비교 대상 클래스가 Comparable을 구현해야 함 | 원본 클래스를 수정하지 않고 외부에서 정의 가능 |
| 주요 사용처 | Collections.sort(list), Arrays.sort(arr) | Collections.sort(list, comparator), TreeMap, TreeSet 등 |
마무리
정리하면, compareTo()는 객체 자신의 기본 정렬 규칙을 클래스 내부에 정의할 때 사용하고, compare()는 클래스 외부에서 원하는 기준대로 정렬 로직을 유연하게 지정할 때 사용합니다. 단일한 기본 정렬이 필요하면 Comparable을, 상황에 따라 다양한 정렬 기준이 필요하면 Comparator를 선택하는 것이 바람직합니다.