[아이템 14] Comparable을 구현할지 고려하라
아이템 14
Comparable을 구현할지 고려하라
CompareTo는 단순 동치성 비교에 더해 순서까지 비교할 수 있으며 제네릭하다. Camparable을 구현했다는 것은 그 클래스의 인스턴스에 순서가 있음을 뜻한다.즉, Caparable을 구현한 객체들의 배열은 바로 정렬할 수 있다.
알파벳, 숫자, 연대 같이 순서가 명확한 값 클래스를 작성한다면 반드시 Comparable 인터페이스를 구현하자.
compareTo 규약
기준 객체 A 가 B보다 작으면 음의 정수를, 같으면 0, 크다면 양의 정수를 반환한다. 만약 A와 비교할 수 없는 객체가 들어온다면 ClassCastException을 던진다.
- sgn(x.compareTo(y)) == -sgn(x.compareTo(y))
첫 번째 객체가 두 번째 객체보다 작으면 두 번째 객체는 첫 번째 객체보다 커야 한다. - x.compareTo(y) > 0 && y.compareTo(z) > 0 이면 x.compareTo(z) > 0이다.
추이성을 보장해야 한다. - x.compareTo(y) == 0이면 sgn(x.compareTo(z)) == sgn(y.compareTo(z))
크기가 같은 객체들끼리는 어떤 객체와 비교하더라도 항상 같아야 한다. - (x.compareTo(y) == 0) == (x.equals(y)) 를 권고한다.
compareTo 메서드로 수행한 동치성 테스트의 결과가 equals와 같아야 한다. 이를 잘 지키면 compareTo로 줄지은 순서와 equals의 결과가 같게 된다.
compareTo의 구현
기본 타입 필드가 여럿일 때의 비교자
public int compareTo(PhoneNumber pn) {
int result = Short.compare(areaCode, pn.areaCode); // 가장 중요한 필드
if (result == 0) {
result = Short.compare(prefix, pn.prefix); // 두 번째로 중요한 필드
if (result == 0) {
result = Short.compare(lineNum, pn.lineNum); // 세 번째로 중요한 필드
}
return result;
}
여럿일 때, 어느 것을 먼저 비교하느냐가 중요해진다. 가장 핵심적인 필드부터 비교하도록 하면 된다.
비교자 생성 메서드를 활용한 비교자
private static final Comparator<PhoneNumber> COMPARATOR =
comparingInt((PhoneNumber pn) -> pn.areaCode)
.thenComparingInt(pn -> pn.prefix)
.thenComparingInt(pn -> pn.lineNum);
public int compareTo(PhoneNumber pn) {
return COMPARATOR.compare(this, pn);
}
위의 방식은 클래스를 초기화할 때 비교자 생성 메서드를 2개 이용해 비교자를 생성한다. compareingInt
는 람다를 인수로 받고 이 람다는 지역 코드를 기준으로 순서를 정하는 Comparator<PhoneNumber>
를 반환한다. 이후의 비교는 thenComparingInt
이 수행한다.
주의할 점
해시 코드의 값의 차를 기준으로 하는 비교자느 사용하면 안된다.
정수 오버플로우를 발생시키거나 부동소수점 계산 방식에서 오류가 발생할 수 있다.
권장하는 방식
정적 compare 메서드
static Comparator<Object> hashCodeOrder = new Comparator<>() {
public int compare(Object o1, Object o2) {
return Integer.compare(o1.hashCode(), o2.hashCode());
}
};
비교자 생성 메서드
static Comparator<Object> hashCodeOrder =
Comparator.comparingInt(o -> o.hashCode());
핵심 정리
순서를 고려하는 값 클래스는 Comparable 인터페이스를 구현하도록 해야한다. 또한 compareTo 메서드에서는 >
, <
연산자는 쓰지 말아야 한다.
Author And Source
이 문제에 관하여([아이템 14] Comparable을 구현할지 고려하라), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jimin3263/아이템-14-Comparable을-구현할지-고려하라저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)