Comparator vs Comparable 완전 정리
자바에서 객체를 정렬할 때 사용하는 두 가지 방식은 Comparable과 Comparator입니다.
코딩테스트나 실무에서 자주 사용되지만 헷갈리기 쉬운 개념입니다.
이 글에서는 두 방식의 차이를 명확하게 이해하고, 예제와 함께 어떤 상황에서 어떤 방식을 쓰는 게 좋은지도 정리해보겠습니다.
1. 개념 요약
| 구분 | Comparable | Comparator |
| 정의 | 객체 스스로 비교 기준을 정의 | 외부에서 비교 기준을 정의 |
| 인터페이스 위치 | java.lang.Comparable | java.util.Comparator |
| 구현 메서드 | compareTo(T o) | compare(T o1, T o2) |
| 사용 위치 | 클래스 내부 | 정렬 시 외부에서 전달 |
| 주요 사용처 | 기본 정렬 기준이 필요할 때 | 유연한 정렬 기준이 필요할 때 |
| 람다식 사용 | 직접 불가 | 람다식으로 표현 가능 |
2. 예제 비교
(1) Comparable 사용 예제 – 클래스 내부에서 compareTo 구현
class User implements Comparable<User> {
String name;
int age;
public int compareTo(User other) {
return this.age - other.age; // 나이 오름차순
}
}
Arrays.sort(users); // 나이 기준 정렬
- Arrays.sort() 사용 가능
- 정렬 기준이 객체 내부에 고정됨
- 코딩테스트에선 거의 사용하지 않음 (객체 수정 불가)
(2) Comparator 사용 예제 – 외부에서 정렬 기준 전달
Arrays.sort(users, new Comparator<User>() {
public int compare(User a, User b) {
return a.age - b.age;
}
});
또는 람다식으로 축약:
Arrays.sort(users, (a, b) -> a.age - b.age); // 나이 오름차순
Arrays.sort(users, (a, b) -> b.age - a.age); // 나이 내림차순
- 유연한 정렬 기준 가능
- 이름 기준, 복합 기준, 내림차순 등 자유롭게 구현
- 코딩테스트에서는 가장 자주 사용됨
3. 코딩테스트 실전 비교
예제 1: 문자열 기준 정렬
Arrays.sort(users, new Comparator<User>() {
public int compare(User a, User b) {
return a.age - b.age;
}
});
- 문자열을 나누어 정렬 기준으로 사용할 때는 Comparator + 람다식이 압도적으로 유리
- String은 compareTo() 메서드를 이미 구현하고 있어 사전순 비교 가능
예제2. Compartor + comparing 사용
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
}
User[] users = {
new User("banana", 25),
new User("apple", 30),
new User("cherry", 20)
};
// comparing() 사용: 이름 기준 오름차순
Arrays.sort(users, Comparator.comparing(User::getName));
// 출력
for (User u : users) {
System.out.println(u.name + " " + u.age);
}
차이
| 항목 | compare() | comparing() |
| 정의 위치 | Comparator 인터페이스의 추상 메서드 | Comparator 인터페이스의 static 헬퍼 메서드 |
| 목적 | 두 객체를 직접 비교 | 객체에서 정렬 기준을 추출하여 Comparator 생성 |
| 사용 방식 | (a, b) -> ... 형태로 구현 | Comparator.comparing(keyExtractor) |
| 코드 위치 | 구현체나 람다에서 직접 사용 | 외부에서 비교 기준을 쉽게 생성 |
예제 3. String의 compareTo() 직접 사용 예시 – 사전순 비교
String a = "apple";
String b = "banana";
if (a.compareTo(b) < 0) {
System.out.println(a + "이 " + b + "보다 사전순으로 앞입니다.");
} else if (a.compareTo(b) > 0) {
System.out.println(a + "이 " + b + "보다 사전순으로 뒤입니다.");
} else {
System.out.println("두 문자열이 같습니다.");
}
예제 4. String 비교 sort 내에서 사용
String[] words = {"banana", "apple", "cherry"};
// compareTo() 직접 사용
Arrays.sort(words, (a, b) -> a.compareTo(b));
// 출력 결과: [apple, banana, cherry]
System.out.println(Arrays.toString(words));
4. compareTo()와 compare()의 차이
| 메서드 | 위치 | 설명 | 사용 예 |
| compareTo() | Comparable 구현 클래스 | 객체 자신이 비교 기준을 갖고 있는 경우 | a.compareTo(b) |
| compare() | Comparator 구현 클래스 or 람다 | 외부에서 두 객체 비교 | (a, b) -> a.age - b.age 또는 Integer.compare(a, b) |
5. 주의사항
❌ 이런 식으로는 안 된다
Arrays.sort(users, (a, b) -> a.name - b.name); // 불가능!
- name은 String이므로 뺄셈(-) 불가
- 반드시 a.name.compareTo(b.name) 사용해야 함
6. 사용 추천 기준
| 상황 | 추천 방식 |
| 기본 정렬 기준을 객체에 부여하고 싶을 때 | Comparable |
| 정렬 기준이 자주 바뀌거나 복합 정렬이 필요할 때 | Comparator + 람다 |
| 코딩테스트에서 사용자 객체 정렬 | Comparator + 람다 (e.g. (a, b) -> a.age - b.age) |
| 문자열 기준 정렬 | a.name.compareTo(b.name) 사용 (String은 Comparable 구현되어 있음) |
7. 결론
- Comparable은 "내가 남과 비교",
- Comparator는 "남을 비교해주는 기준을 외부에서 줌"
- 코딩테스트에서는 보통 Comparator + 람다식으로 유연하게 처리하는 방식이 주류
- 기본 타입들(Integer, String, Double 등)은 compareTo()가 이미 구현되어 있어 바로 사용 가능
'자바 > 자바' 카테고리의 다른 글
| 인프런 강의 정리_ JAVA 성능 튜닝과 트러블 슈팅 * 휴먼넷 (1) | 2025.08.31 |
|---|---|
| (자바)자바 제너릭 (Generics) 정리 (0) | 2025.08.21 |
| (자바) equals(), hashCode(), toString()의 역할 (0) | 2025.07.07 |
| (JAVA) java.lang 패키지란 (0) | 2025.07.06 |
| (자바) 스프링과 리플렉션 정리2 (0) | 2025.06.25 |