순서를 고려해야 하는 값 클래스를 작성한다면 꼭 Comparable 인터페이스를 구현하여, 그 인스턴스들을 쉽게 정렬하고, 검색하고, 비교 기능을 제공하는 컬렉션과 어우러지도록 해야 함. compareTo 메서드에서 필드의 값을 비교할 때 <와 > 연산자는 쓰지 말아야 한다. 그 대신 박싱된 기본 타입 클래스가 제공하는 정적 compare 메서드나 Comparator 인터페이스가 제공하는 비교자 생성 메서드를 사용하자.
Comparable 인터페이스. compareTo 메서드
- compareTo는 단순 동치성 비교에 더해 순서까지 비교할 수 있으며, 제너릭함(이 두가지를 제외하면 equals와 성격이 같음)
- Comparable을 구현했다는 것은 그 클래스의 인스턴스들에 자연적인 순서(natural order)가 있음을 뜻함
- 알파벳, 숫자, 연대 같이 순서가 명확한 값 클래스를 작성한다면 반드시 Comparable 인터페이스를 구현하자
compareTo 메서드의 일반규약 . equals의 규약과 비슷함

- 두 객체 참조의 순서를 바꿔 비교해도 예상한 결과가 나와야 함 (대칭성 - symmetricity)
- a< b 이고 b < c 이면 a< c 여야 함(추이성 — transitivity)
- compareTo와 equals로 동등성비교한 것의 결과가 같아야 한다
- equals와는 달리 모든 객체에 대해 전역 동치관계를 부여하지 않고, 타입이 다른 객체면 ClassCastException을 던짐
- compareTo 규약을 지키지 못하면 비교를 활용하는 클래스와 어울리지 못함
- 예시 : TreeSet, TreeMap, Collections, Arrays
- equals에서와 마찬가지로 기존 클래스를 확장한 구체 클래스에서 새로운 값 컴포넌트를 추가 했다면 compareTo 규약을 지킬 방법이 없음
- 우회법도 마찬가지. Composition으로
- 마지막 규약이 지켜지지 않아도 여전히 동작은 하지만 이 객체를 정렬된 컬렉션에 넣으면 해당 컬렉션이 구현한 인터페이스에 정의된 동작과 다르게 동작할 것임
- 예로 compareTo와 equals가 일관되지 않는 BigDecimal 클래스에서 new BigDecimal(”1.0”), new BigDecimal(”1.00”)에 대해
- HashSet인스턴스는 둘을 다르게 봄. 원소 2개 (equals를 이용하기에)
- TreeSet은 원소 하나만 갖게 됨(compareTo 메서드로 비교하기에)
비교 방법
객체 참조 필드가 하나뿐인 비교자
public final class CaseInsensitiveString implements Comparable<CaseInsensitiveString>{ // 자바가 제공하는 비교자를 사용해 클래스를 비교한다. public int compareTo(CaseInsensitiveString cis) { return String.CASE_INSENSITIVE_ORDER.compare(s, cis.s); } }
CaseInsensitiveString implements Comparable<CaseInsensitiveString>
Comparable 구현 시 일반적으로 따르는 패턴
- compareTo 메서드에서 정수, 실수, 기본타입들 비교시 정적 메서드 이용하기. Integer.compare, Double.compare, Float.compare
기본 타입 필드가 여럿일 때의 비교자
- 핵심 필드가 여러개라면 제일 중요한 것부터 비교하고 0이 아니면 바로 반환. 0이라면 그 다음 비교로 넘어가는 식으로 구성
Comparator 인터페이스의 비교자 생성메서드를 이용한 compareTo 구현
private static final Comparator<PhoneNumber> COMPARATOR = comparingInt((PhoneNumber pn) -> pn.areaCode) .thenComparingInt(pn -> pn.prefix) .thenComparingInt(pn -> pn.lineNum); public int compareTo(PhoneNumber pn) { return COMPARATOR.compare(this, pn); }
- 간단하지만 약간의 성능저하가 있음
- Comparator는 수많은 보조 생성 메서드들 가지고 있으니 잘 활용하자!