- 작성일 : 2026-05-29
- 관련 문제 : PG42579 베스트 앨범
- 관련 문서 : Comparator 정렬 기준, Map 정렬과 computeIfAbsent
Comparable은 객체가 자기 자신의 기본 정렬 기준을 가지게 만드는 인터페이스다. Song끼리는 어떤 순서로 놓을지, Genre끼리는 어떤 순서로 놓을지를 객체 안에 직접 정의할 때 사용한다.
Comparable을 쓰는 기준
객체에 자연스럽고 대표적인 정렬 기준이 하나 있다면 Comparable을 고려한다.
| 상황 | 선택 |
|---|---|
| 객체의 기본 정렬 기준이 분명하다 | Comparable |
| 상황마다 정렬 기준이 바뀐다 | Comparator |
| 정렬이 한 번만 필요하고 간단하다 | 람다 Comparator |
| 같은 타입을 여러 기준으로 정렬한다 | Comparator를 여러 개 만든다 |
베스트 앨범에서는 Song의 정렬 기준이 문제 안에서 거의 고정된다. 재생 횟수 내림차순, 동률이면 고유 번호 오름차순이다. 그래서 Song implements Comparable<Song>로 둘 수 있다.
compareTo 반환값
compareTo도 Comparator와 같은 반환 규칙을 가진다.
this.compareTo(other)가 음수면 this가 앞에 온다
this.compareTo(other)가 양수면 other가 앞에 온다
this.compareTo(other)가 0이면 같은 순서다
예를 들어 Song에서 재생 횟수가 큰 노래가 앞에 와야 한다면 다음처럼 쓴다.
@Override
public int compareTo(Song other) {
return Integer.compare(other.playCount, this.playCount);
}
this.playCount가 100이고 other.playCount가 300이면 Integer.compare(300, 100)은 양수다. 양수면 other가 앞에 온다. 그래서 재생 횟수 내림차순이 된다.
동률 조건 넣기
정렬 기준이 여러 개면 우선순위가 높은 조건부터 비교한다.
@Override
public int compareTo(Song other) {
if (this.playCount != other.playCount) {
return Integer.compare(other.playCount, this.playCount);
}
return Integer.compare(this.index, other.index);
}
| 조건 | 방향 | 코드 |
|---|---|---|
| 재생 횟수 | 내림차순 | Integer.compare(other.playCount, this.playCount) |
| 고유 번호 | 오름차순 | Integer.compare(this.index, other.index) |
동률 조건을 빼먹으면 예제는 맞아도 숨은 테스트에서 틀릴 수 있다.
Comparable 객체끼리 비교하기
Comparable을 구현한 객체는 직접 비교할 수 있다.
Song a = new Song(0, 500);
Song b = new Song(1, 300);
int result = a.compareTo(b);
result가 음수면 a가 앞이다. 양수면 b가 앞이다.
정렬 API도 내부적으로 이 기준을 사용한다.
songs.sort(Song::compareTo);
Collections.sort(songs);
Map.Entry.comparingByValue()도 value가 Comparable이면 그 기준을 사용한다.
genreMap.entrySet().stream()
.sorted(Map.Entry.comparingByValue());
여기서 value인 Genre가 Comparable<Genre>를 구현하고 있어야 자연스럽게 정렬된다.
주의할 점
compareTo에서 뺄셈을 쓰는 습관은 피한다.
return other.playCount - this.playCount;
이 방식은 짧지만 값 범위가 커지면 오버플로우 위험이 있고, 정렬 방향도 헷갈리기 쉽다.
대신 다음처럼 쓴다.
return Integer.compare(other.playCount, this.playCount);
실수 체크
- 객체의 기본 정렬 기준이 하나로 고정되는가
-
this.compareTo(other)가 음수면this가 앞이라는 기준을 기억했는가 - 내림차순이면
Integer.compare(other, this)방향인지 확인했는가 - 동률 조건을 문제에 나온 순서대로 처리했는가
- 뺄셈 비교 대신
Integer.compare를 썼는가