콘텐츠로 이동

비교

Comparable, Comparator

왜 사용하는가?

  • 객체를 정렬하거나 대소 비교할 때, 기본 타입과 달리 객체는 >, < 연산자를 사용할 수 없음
  • 정렬 기준을 명시적으로 정의하기 위해 사용
  • TreeSet, TreeMap, Arrays.sort(), Collections.sort() 등이 내부적으로 비교 인터페이스를 활용

특이점

  • 구현하지 않고 비교 시도 → ClassCastException 발생
  • TreeSet, TreeMap은 반드시 비교 기준이 있어야 동작

Comparable

  • [비교 가능한]이라는 뜻
  • 객체 자신이 가지는 기본 정렬 기준(natural ordering)을 정의
  • "이 타입은 이렇게 정렬되는 것이 기본이다"를 명시
  • compareTo(T o) 메서드 구현

반환값 규칙

반환값 의미
음수 thiso보다 작음
0 같음
양수 thiso보다 큼
class Member implements Comparable<Member> {
    String name;
    int age;

    @Override
    public int compareTo(Member o) {
        return this.name.compareTo(o.name); // 이름 기준 오름차순
        // return this.age - o.age; // 나이 기준 오름차순
    }
}

Comparator

  • [비교자]라는 뜻
  • 객체 외부에서 정의하는 정렬 전략
  • 상황·화면·정책에 따라 정렬 기준을 유연하게 변경 가능
  • compare(T o1, T o2) 메서드 구현
class AgeComparator implements Comparator<Member> {
    @Override
    public int compare(Member o1, Member o2) {
        return Integer.compare(o1.getAge(), o2.getAge()); // 나이 오름차순
    }
}

// 람다로 간결하게
Comparator<Member> byAge = (o1, o2) -> Integer.compare(o1.getAge(), o2.getAge());
Comparator<Member> byName = Comparator.comparing(Member::getName);
Comparator<Member> byAgeDesc = Comparator.comparingInt(Member::getAge).reversed();

Comparable vs Comparator

항목 Comparable Comparator
위치 객체 내부 객체 외부
메서드 compareTo(T o) compare(T o1, T o2)
정렬 기준 기본 정렬 1가지 다양한 정렬 전략
변경 코드 수정 필요 전략 교체만으로 변경 가능

Tree 구조에서의 사용

  • TreeSet, TreeMap은 요소 삽입 시 정렬 기준이 반드시 필요
  • Comparable 구현 객체: 자동으로 기본 정렬
  • Comparator 전달: 정렬 기준을 직접 지정

어떻게 사용하는가?

Member member1 = new Member("A", 10);
Member member2 = new Member("B", 20);
Member[] members = {member2, member1};

// Comparable 기반 정렬 (기본 정렬)
Arrays.sort(members);

// Comparator 기반 정렬 (나이 기준)
Arrays.sort(members, new AgeComparator());
Arrays.sort(members, (o1, o2) -> Integer.compare(o1.getAge(), o2.getAge()));

// 컬렉션 정렬
List<Member> list = new ArrayList<>(List.of(member1, member2));
list.sort(null);                        // Comparable 기본 정렬
list.sort(new AgeComparator());         // Comparator 지정
Collections.sort(list);                 // Comparable 기본 정렬

// TreeSet
Set<Member> treeSet1 = new TreeSet<>();                    // Comparable 기반
Set<Member> treeSet2 = new TreeSet<>(new AgeComparator()); // Comparator 지정

어떨 때 많이 쓰는가?

상황 선택
객체의 자연스러운 기본 순서 정의 Comparable
다양한 정렬 기준이 필요 (이름순, 나이순 등) Comparator
TreeSet/TreeMap에 커스텀 객체 사용 둘 중 하나 필수
정렬 기준을 런타임에 결정 Comparator (람다 활용)