Comparable을 구현할지 고려하라
CompareTo는 단순 동치성 비교에 더해 순서까지 비교할 수 있으며 제네릭하다. Camparable을 구현했다는 것은 그 클래스의 인스턴스에 순서가 있음을 뜻한다.즉, Caparable을 구현한 객체들의 배열은 바로 정렬할 수 있다.
알파벳, 숫자, 연대 같이 순서가 명확한 값 클래스를 작성한다면 반드시 Comparable 인터페이스를 구현하자.
기준 객체 A 가 B보다 작으면 음의 정수를, 같으면 0, 크다면 양의 정수를 반환한다. 만약 A와 비교할 수 없는 객체가 들어온다면 ClassCastException을 던진다.
기본 타입 필드가 여럿일 때의 비교자
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 메서드에서는 >
, <
연산자는 쓰지 말아야 한다.