CS/Java

[Java]Comparable과 Comparator

munsik22 2026. 8. 1. 10:59

Java에서 Comparable과 Comparator는 객체를 정렬하거나 비교할 때 주로 사용하는 인터페이스이다. 둘 다 "두 객체의 순서를 비교한다"는 목적은 같지만, 비교 기준을 어디에 정의하느냐가 다르다.

🧩 Comparable

Comparable객체 자신이 기본 정렬 기준을 갖도록 만드는 인터페이스다.

 

클래스가 Comparable<T>를 구현하고 compareTo()를 오버라이드한다.

public interface Comparable<T> {
    int compareTo(T other);
}

 

compare()는 다음 규칙으로 값을 반환한다.

  • 음수: 현재 객체가 비교 대상보다 작음
  • 0: 두 객체가 같음
  • 양수: 현재 객체가 비교 대상보다 큼

아래 예시는 나이를 기준으로 오름차순/내림차순 정렬하는 것이다.

class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person other) {
        return Integer.compare(this.age, other.age);
    }

    @Override
    public String toString() {
        return name + "(" + age + ")";
    }
}

List<Person> people = new ArrayList<>();
people.add(new Person("민수", 30));
people.add(new Person("준수", 25));
people.add(new Person("철수", 28));

// 오름차순 정렬
Collections.sort(people);
System.out.println(people); // [준수(25), 철수(28), 민수(30)]

// 내림차순 정렬
Collections.sort(people, Collections.reverseOrder());
System.out.println(people); // [민수(30), 철수(28), 준수(25)]

🧩 Comparator

Comparator객체 외부에서 비교 기준을 별도로 정의하는 인터페이스다.
public interface Comparator<T> {
    int compare(T o1, T o2);
}

 

Comparable과는 달리 대상 클래스 자체를 수정하지 않아도 되고, 여러 정렬 기준을 만들기에 적합하다.

// 이름 기준 정렬
Comparator<Person> nameComparator = new Comparator<Person>() {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getName().compareTo(p2.getName());
    }
};

 

Lambda를 사용하면 더 간단하게 표현할 수 있다.

Comparator<Person> nameComparator = (p1, p2) -> p1.getName().compareTo(p2.getName());
people.sort(nameComparator);

// 또는
// people.sort((p1, p2) -> p1.getName().compareTo(p2.getName()));

System.out.println(people); // [민수(30), 지수(25), 철수(28)]

 

Java 8+ 에서는 Comparator.comparing()을 쓰는 방식을 사용하기도 한다.

// 이름 기준 정렬
people.sort(Comparator.comparing(Person::getName));

// 나이 기준 정렬
people.sort(Comparator.comparingInt(Person::getAge));

// 나이 기준 내림차순 정렬
people.sort(Comparator.comparingInt(Person::getAge).reversed());

여러 조건으로 정렬하기

  • compareTo()
// 나이 오름차순, 나이가 같으면 이름 오름차순
people.sort((p1, p2) -> {
    int ageCompare = Integer.compare(p1.getAge(), p2.getAge());
    if (ageCompare != 0) {
        return ageCompare;
    }
    return p1.getName().compareTo(p2.getName());
});

// 나이 내림차순, 이름 오름차순
people.sort((p1, p2) -> {
    int ageCompare = Integer.compare(p2.getAge(), p1.getAge());
    if (ageCompare != 0) {
        return ageCompare;
    }
    return p1.getName().compareTo(p2.getName());
});
  • compareTo() + Lambda
// 나이 오름차순, 이름 오름차순
people.sort((p1, p2) -> p1.getAge() != p2.getAge() 
    ? Integer.compare(p1.getAge(), p2.getAge()) 
    : p1.getName().compareTo(p2.getName()));

// 나이 내림차순, 이름 오름차순
people.sort((p1, p2) -> p1.getAge() != p2.getAge() 
    ? Integer.compare(p2.getAge(), p1.getAge()) 
    : p1.getName().compareTo(p2.getName()));
  • comparingInt()
// 나이 오름차순, 나이가 같으면 이름 오름차순
people.sort(
    Comparator.comparingInt(Person::getAge)
              .thenComparing(Person::getName)
);

// 나이 내림차순, 이름 오름차순
people.sort(
    Comparator.comparingInt(Person::getAge)
              .reversed()
              .thenComparing(Person::getName)
);

🧩 Comparable vs Comparator

구분 Comparable Comparator
위치 비교 대상 클래스 내부 클래스 외부
메서드 compareTo(T o) compare(T o1, T o2)
정렬 기준 기본 1개 여러 개 가능
클래스 수정 필요 필요X
사용 목적 자연 정렬 상황별/custom 정렬
예시 문자열 사전순, 숫자 크기순 이름순, 가격순, 날짜순 등

Comparable을 사용하는 경우

객체에 명확한 기본 정렬 기준이 있을 때 사용한다.

  • String: 사전순
  • Integer: 숫자순
  • LocalDate: 날짜순
  • 회원 객체: 회원 번호순
  • 상품 객체: 상품 ID순
class Product implements Comparable<Product> {
    private long id;

    @Override
    public int compareTo(Product other) {
        return Long.compare(this.id, other.id);
    }
}

Comparator를 사용하는 경우

정렬 기준이 여러 개이거나 상황에 따라 달라질 때 사용한다.

  • 회원을 이름순 / 가입일순 / 포인트순으로 정렬
  • 상품을 가격순 / 판매량순 / 평점순으로 정렬
  • 외부 라이브러리 클래스처럼 수정할 수 없는 클래스 정렬
  • 화면 또는 API 요청 파라미터에 따라 정렬 방식 변경

 

'CS > Java' 카테고리의 다른 글

[Java]Lambda 와 Stream  (0) 2026.07.31
[Java]Generics  (0) 2026.07.26
Java로 멀티 쓰레드 찍먹하기  (0) 2026.02.21