공식문서 파헤치기
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
'개발 > 자바' 카테고리의 다른 글
추상화란? (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 |
이전 댓글