Comparable 인터페이스
- Comparable을 구현해다는 것은 그 클래스의 인스턴스들에는 자연적인 순서가 있음을 뜻한다.
- Comparable을 구현한 객체들의 배열은 손쉽게 정렬할 수 있다. (Arrays.sort(a);)
- 자바 플랫폼 라이브러리의 모든 값 클래스와 열거 타입(아이템 34)이 Comparable을 구현했다.
public interface Comparable<T> {
int compareTo(T t);
}
compareTo 메서드의 일반 규약
- 이 객체와 주어진 객체의 순서를 비교한다.
- 이 객체가 주어진 객체보다 작으면 음의 정수를, 같으면 0을, 크면 양의 정수를 반환한다.
- 이 객체와 비교할 수 없는 타입의 객체가 주어지면 ClassCastException을 던진다.
- sgn(부호 함수): 표현식의 값이 음수, 0 양수일 때 -1, 0, 1을 반환한다.
- sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
- (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)), 필수는 아니다.
- 이 규약을 지키지 않으면, Collection, Set, Map은 동치성을 비교할 때 equals 대신 compareTo를 사용하기 때문에 의도치 않은 결과를 낼 수 있다.
객체 참조 필드가 하나뿐인 비교자
public final class CaseInsensitiveString implements Comparable<CaseInsensitiveString> {
public int compareTo(CaseInsensitiveString cis) {
return String.CASE_INSENSITIVE_ORDER.compare(s, cis.s);
}
}
기본 타입 필드가 여럿일 때의 비교자
약간의 성능 저하가 발생한다.
public int compareTo(PhoneNumber pn) {
int result = Short.compare(areaCode, pn.areaCode); // 가장 중요한 필드
if (result == 0) {
result = Short.compare(prefix, pn.prifix); // 두번째로 중요한 필드
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);
}
사용하면 안 되는 방식
- compareTo 메서드에서 관계 연산자 <와 >를 사용하는 이전 방식은 거추장스럽고 오류를 유발하니, 이제는 추천하지 않는다.
- 이따금 ‘값의 차'를 기준으로 첫 번째 값이 두번째 값보다 작으면 음수를, 두 값이 같으면 0을, 첫번째 값이 크면 양수를 반환하는 방식은 사용하면 안 된다. 이 방식은 정수 오버플로를 일으키거나 IEEE 754 부동소수점 계산 방식에 따른 오류를 낼 수 있다.
핵심 정리
- 순서를 고려해야 하는 값 클래스를 작성한다면 꼭 Comparable 인터페이스를 구현해야 한다.
- compareTo 메서드에서 필드의 값을 비교할 때 <와 > 연산자는 쓰지 말자.
- 박싱된 기본 타입 클래스가 제공하는 정적 compare 메서드나 Comparator 인터페이스가 제공하는 비교자 생성 메서드를 사용하자.
'이펙티브 자바' 카테고리의 다른 글
아이템 4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2022.05.17 |
---|---|
아이템 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2022.05.16 |
아이템 2. 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2022.04.21 |
아이템 1. 생성자 대신 정적 팩터리 메서드를 고려하라 (0) | 2022.04.05 |
아이템 13. clone 재정의는 주의해서 진행하라 (0) | 2022.02.12 |
댓글