본문 바로가기
개발/자바

Comparable의 compareTo() 파헤치기

by hamcheeseburger 2022. 2. 14.

공식문서 파헤치기

Comparable 인터페이스에는 compareTo() 라는 메소드가 존재한다. 오늘은 이것에 대해 공부할 것 이다.

Description (설명) : 

Compares this object with the specified object for order.

현재 객체와 특정 객체를 비교하여 순서를 지정한다.

 

Method Detail을 보자!

Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

현재 객체와 특정 객체를 비교하여 순서를 지정한다. 현재 객체가 더 작을 때는 음수를, 같을 때는 0을, 더 클때는 양수를 반환한다.

 

The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception if y.compareTo(x) throws an exception.)

*구현체는 모든 x와 y에 대해 **Math.signum(x.compareTo(y)) == -Math.signum(y.compareTo(x)) 라는 점을 보장해야한다. (이는 y.compareTo(x)가 예외를 발생하면, x.compareTo(y)도 예외가 발생한다는 것을 뜻하기도 한다.)

 

* implements 키워드를 통해 Comparable을 구현한 객체

**Math.signum(x)은 x의 부호를 반환하는 함수다.

 

The implementor must also ensure that the relation is transitive: (x.compareTo(y) > 0) && y.compareTo(z) > 0) implies x.compareTo(z) > 0.

또한 구현체는 관계가 변환될 수 있음을 보장해야 한다. (x.compareTo(y) > 0 && y.compareTo(z) > 0는 x.compareTo(z) > 0임을 암시한다.) 즉, x > y 이고 y > z 이면 x > z임을 보장해야 한다.

 

Finally, the implementor must ensure that x.compareTo(y) == 0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.

마지막으로, 구현체는 모든 z에 대해서 x.compareTo(y) == 0 이면 Math.signum(x.compareTo(z)) == Math.signum(y.compareTo(z)) 임을 보장해야 한다. 즉, x와 y가 같으면 x와 z의 비교 값과 y와 z의 비교 값의 부호가 같아야 한다.

 

Parameters:
o - the object to be compared.

파라미터 :

o - 비교될 객체

 

Throws:
NullPointerException - if the specified object is null
ClassCastException - if the specified object's type prevents it from being compared to this object.

예외 던지기:

NullPointerException - 전달 받은 객체가 null인 경우 발생한다.

ClassCastException - 전달 받은 객체의 타입이 현재 객체와 비교할 수 없는 경우 발생한다.

 

 

 

적용해보기

비교대상이 숫자일 때

public class RacingCar implements Comparable<RacingCar> {
	
    private final String name;
    private int position;

    @Override
    public int compareTo(RacingCar anotherCar) {
        return this.position - anotherCar.position;
    }
}

보통 숫자를 정렬 대상으로 둔다면 위와 같이 (현재 객체가 가지고 있는 숫자 - 전달 받은 객체가 가지고 있는 숫자)의 형식으로 간단히 반환할 수 있다. (현재 객체가 클 경우엔 양수, 같을 때는 0, 작을 때는 음수를 반환해야 함으로)

 

비교대상이 문자열일 때 (String의 compareTo())

두 문자열을 각 위치의 문자끼리 비교했을 때, 문자가 서로 다른 경우에 아스키 코드의 차를 반환한다.

두 문자열을 각 위치의 문자끼리 비교했을 때, 어느 한 문자열이 다른 문자열에 포함되는 경우엔 두 문자열의 길이의 차를 반환한다.

public class RacingCar implements Comparable<RacingCar> {
	
    private final String name;
    private int position;

    @Override
    public int compareTo(RacingCar anotherCar) {
        return name.compareTo(anotherCar.name);
    }
}

 

@Test
void compareTo_반환값을_테스트한다() {
    RacingCar a = new RacingCar("abcd");
    RacingCar b = new RacingCar("abc");

    assertThat(a.compareTo(b)).isEqualTo(1);
}

위의 코드는 "abc"가 "abcd"에 포함되는 경우이다. 이 때는 두 문자열의 길이의 차를 반환하므로, 4 - 3의 결과로 1이 반환된다. ("abcd" 길이 - "abc"길이)

 

@Test
void compareTo_반환값을_테스트한다() {
    RacingCar a = new RacingCar("abcd");
    RacingCar b = new RacingCar("abce");

    assertThat(a.compareTo(b)).isEqualTo(-1);
}

위의 경우에는 어느 문자열이 다른 문자열에 포함되는 상황은 아니다. 이 경우에는 각 자리의 문자끼리 비교해서 다른 문자일 경우 아스키 코드 값의 차를 반환한다. 'd'와 'e' 가 다르기 때문에 d의 아스키코드 값(100) - e의 아스키코드 값(101)의 결과로 -1이 반환된다.

 

@Test
void compareTo_반환값을_테스트한다() {
    RacingCar a = new RacingCar("abcd");
    RacingCar b = new RacingCar("ABCD");

    assertThat(a.compareTo(b)).isEqualTo(32);
}

위의 경우도 마찬가지로 'a'와 'A'는 다른 문자이기 때문에 a의 아스키 코드 값(97) - A의 아스키 코드 값(65)의 결과로 32가 반환이 된다.

 

 

 

 

공식문서 : https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html

 

Comparable (Java Platform SE 8 )

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method. Lists (and arrays) of o

docs.oracle.com

'개발 > 자바' 카테고리의 다른 글

추상화란?  (2) 2022.03.17
compareTo()가 0을 반환하면 어떤 순서로 정렬되나?  (0) 2022.02.19
Java Stream.max() 사용법  (0) 2022.02.14
JUnit 사용법  (0) 2022.02.11
[Java] clone()에 대해서  (0) 2021.05.17

이전 댓글