-
Item 14. Comparable을 구현할지 고려하라백수의 개발/이펙티브 자바 2019. 9. 29. 19:45
Comparable의 compareTo()는 단순 동치성 비교뿐만 아니라 순서까지 비교할 수 있으며, 제네릭하다.
따라서 Comparable을 구현했다는 것은 해당 클래스의 순서가 있음을 의미한다.
그로 인해 아래와 같이 간단하게 정렬을 사용할 수 있는 객체가 된다.
Arrays.sort(a);
CompareTo 메서드의 일반 규약
- 이 객체와 주어진 객체의 순서를 비교한다.
- 이 객체가 주어진 객체보다 작으면 음의 정수(-1)를, 같으면 0을, 크면 양의 정수(1)를 반환한다.
- 이 객체와 비교할 수 없는 타입이 주어지면 ClassCaseException을 던진다.
1. 대칭성
Comparable을 구현한 클래스는 모든 x, y에 대해 sgn(x.compareTo(y)) == -sgn(y.compareTo(x))여야 한다.
따라서 x.compareTo(y)가 예외를 던지면, y.compareTo(x)도 예외를 던져야한다.
2. 추이성
(x.compareTo(y) > 0 && y.compareTo(z) > 0)이면 x.compareTo(z) > 0이다.
3. 반사성
x.compareTo(y) == 0이면 sgn(x.compareTo(z)) == sgn(y.compareTo(z))이다.
4. equals
이는 필수는 아니지만 꼭 지키는 것이 좋다.
(x.compareTo(y) == 0) == (x.equals(y))이다. 이를 지키지 않는 모든 클래스는 그 사실을 명시해야한다.
(* 주의 : 이 클래스의 순서는 equals 메서드와 일관되지 않다.)
CompareTo 구현 패턴
- 관계 연산자 "<", ">"를 사용하는 것은 거추장스럽고 오류를 유발하니 피해라.
public int compareTo(int x, int y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); }
- 기본타입인 경우 박싱된 기본타입 클래스의 compare()함수, 또는 비교 클래스 자체의 compare()을 사용해라.
public int compareTo (int x, int y) { return Integer.compare(x, y); }
- 가장 핵심적인 필드부터 비교하자. 불필요한 연산을 줄여줄 것 이다.
public int compareTo(PhoneNumber pn) { int result = Short.compare(this.areaCode, pn.areaCode); if(result == 0) { result = Short.compare(this.prefix, pn.prefix); if(result == 0) { result = Short.compare(this.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); }
마무리
순서를 고려해야 하는 값 클래스를 작성한다면 꼭 Comparable 인터페이스를 구현하여, 그 인스턴스들을 쉽게 정렬하고, 검색하고, 비교 기능을 제공하는 컬렉션과 어우러지도록 해야 한다.
compareTo 메서드에서 필드의 값을 비교할 때 "<"와 ">" 연산자는 쓰지 말도록 하자.
대신 박싱된 기본 타입 클래스가 제공하는 정적 compare메서드나 Comparator 인터페이스가 제공하는 비교자 생성 메서드를 사용하자.
'백수의 개발 > 이펙티브 자바' 카테고리의 다른 글
Item 16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 (0) 2019.10.01 Item 15. 클래스와 멤버의 접근 권한을 최소화하라 (0) 2019.09.30 Item 13. clone 재정의는 주의해서 진행하라 (0) 2019.08.27 Item 12. toString을 항상 재정의하라 (0) 2019.08.22 Item 11. equals를 재정의하려거든 hashCode도 재정의하라 (0) 2019.08.20