본문 바로가기
Learning-log/JAVA

[Java] Comparable, Comparator 알아보기

by why제곱 2023. 3. 23.

본 게시물에서는 Comparable과 Comparator에 대해 알아보려 한다. 

 

Comparable과 Comparator는 모두 인터페이스(Interface)이며 객체를 비교하기 위해 사용한다. 이 둘 모두 인터페이스인 관계로, 사용하기 위해서는 각각에 선언된 메소드를 반드시 구현해야한다. 어떤 메서드를 구현해야 하는지, 어떤 차이가 있는지, 사용하는 방법은 무엇인지 자세히 알아보자.

 

1. Comparable

주로 객체의 자연스러운 순서를 정의할 때 사용된다. 따라서 객체의 비교를 구현하고 싶을 때(객체 자체가 정렬 가능해지도록 하고 싶을 때)나 클래스를 수정할 수 있는 경우에 사용한다.

 

그럼 Java 공식 API문서에 Comparable을 찾아보자.

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Comparable.html

 

Comparable (Java SE 17 & JDK 17)

Type Parameters: T - the type of objects that this object may be compared to All Known Subinterfaces: ArrayType, ByteValue, CharValue, ChronoLocalDate, ChronoLocalDateTime , Chronology, ChronoZonedDateTime , ClassType, Delayed, DoubleValue, Field, FloatVal

docs.oracle.com

해당 인터페이스는 java.lang에 속해있었다.

위 링크를 통해 살펴본 Comparable에 선언된 메서드는 다음과 같다.

 

즉 Comparable을 사용하기 위해서는 compareTo 메서드를 구현해야 한다. compareTo 메서드는 매개변수로 객체 하나를 입력받아 자기 자신과 매개변수를 메서드에 정의된 구현 형태대로 비교하여 반환한다. 

 

 

메서드 동작을 조금 더 자세히 살펴보자면 int를 반환한다. 자기 자신 객체와 매개변수 객체를 비교하여 반환값이 양수라면 자기자신이, 음수라면 매개변수가 더 큰 값임을 의미한다. 0이 반환된다면 두 객체가 같음을 의미한다. 이를 이용해서 반환값이 양수, 0, 음수 중 어느 값이냐에 따라 sort 기능을 사용할 때 활용한다. 

 

Comparable을 사용한 예제 코드를 살펴보자.

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

    // Constructors, getters, and setters...

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

 

 

2. Comparator

객체들 간의 정렬 순소를 외부에서 제공하고자 할 때 사용되는 인터페이스이다. 주로 이미 존재하는 클래스의 정렬방식을 변경하거나, 다양한 정렬 방식을 제공할 때, 그리고 클래스를 수정할 수 없는 경우에 사용된다. 

 

마찬가지로 Java 공식 API 문서의 Comparator를 찾아보자.

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Comparator.html

 

Comparator (Java SE 17 & JDK 17)

Type Parameters: T - the type of objects that may be compared by this comparator All Known Implementing Classes: Collator, RuleBasedCollator Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambd

docs.oracle.com

 

java.util에 속해있음을 알 수 있었으며 선언된 메서드들은 아래 사진과 같았다.

 

위와 같은 메서드들이 있지만, 실제 Comparator를 사용할 때는 compare를 제외한 다른 메서드들을 모두 구현해주지 않아도 된다. compare 외의 메서드들은 Java 8에서 추가된 것으로, 편리성을 위해 제공되었기 때문이다.  

 

Intellij에서 직접 해당 인터페이스를 타고 들어가봤더니 아래와 같은 문서를 확인할 수 있었다.

 

equals는 Object에서 구현된 메서드를 상곡받아 재사용하기 때문에 구현할 필요가 없으며 그 외의 메서드들 모두 이미 return 값이 존재해 구현을 반드시 할 필요는 없다.

 

그렇다면 compare 메서드를 어떻게 사용하는 지 살펴보자.

compare 메서드는 두개의 객체를 매개변수로 받아 비교한다. 첫번째 매개변수가 두번째 매개변수보다 작으면 음수, 같으면 0, 크면 양수를 반환하며 마찬가지로 이는 sort에서 활용될 수 있다.

 

그럼 Comparator를 사용한 예제 코드를 살펴보자.

import java.util.Comparator;

public class PersonAgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }
}

 

 

3. 비교 정리

  • Comparable을 사용하는 경우:
    • 객체가 자연스러운 정렬 순서를 가지고 있을 때.
    • 클래스의 기본 정렬 순서를 제어하고 싶을 때.
  • Comparator를 사용하는 경우:
    • 이미 구현된 클래스의 정렬 기준을 변경하고자 할 때.
    • 여러 정렬 기준이 필요하거나 동적으로 정렬 기준을 변경하고 싶을 때.
    • 다른 정렬 기준을 가진 객체들을 비교하고 싶을 때.