1. compareTo()와 equals()의 차이
compareTo는 Object의 메서드가 아니다.
성격은 두가지만 빼면 Object의 equals와 같다.
- compareTo는 단순 동치성 비교에 더해 순서까지 비교 가능하다.
- 그 클래스의 인스턴스들에 자연적인 순서가 있음을 뜻할 수 있다.
그래서 Comparable을 구현한 객체들의 배열은 손쉬운 정렬이 가능하다.
알파벳, 숫자, 연대 등 순서가 명확한 값 클래스 작성할땐 구현하자.
2. CompareTo() 메서드 규약
equals와 같은 내용이다 (주의점, 우회법 모두 같다.)
this < object : -1
this == object : 0
this > object : 1
ㄱ. 반사성, 대칭성, 추이성을 충족해야한다
● sgn(x.compareTo(y) == -sgn(y.compareTo(x))
x.compareTo(y)는 y.compareTo(x)가 예외를 던질 때에 한해 예외를 던진다.
두 객체 참조의 순서를 바꾸어 비교해보아도 예상한 결과가 나와야한다.
● x.compareTo(y) > 0 && y.compareTo(z) > 0이면 x.compareTo(z) > 0 이다.
첫번째가 두번째보다 크고 두번째가 세번째보다 크면, 첫번째는 세번째보다 크다.
● Comparalbe을 구현한 클래스는 모든 z에 대해 x.compareTo(y) == 0 이면 sgn(x.compareTo(z)) == sgn(y.compareTo(z)) 이다.
크기가 같은 객체들끼리 어떤 객체와 비교해도 항상 같아야한다.
● (x.compareTo(y) == 0) == (x.equals(y)) 여야 한다.
compareTo로 수행한 동치성 테스트의 결과가 equals와 같아야한다.
지키지 않을 때는 명시해야한다. "주의 : 이 클래스의 순서는 equals 메서드와 일관되지 않는다."
컬렉션 구현 인터페이스(Collection, Set, Map) - 구현에 따른 주의가 필요하기 때문이다.
: equals 메서드 규약을 따른다 되어있다.
: 정렬된 컬렉션들은 동치성 비교시 equals대신 compareTo 사용
ㄴ. 기존 클래스를 확장한 구체클래스에서 새로운 값 컴포넌트를 추가하면 compareTo 지킬 방법이 없다.
우회법 : 컴포지션을 사용하고 + '뷰' 메서드를 제공하자
3. compareTo 메서드 작성요령
equals와의 차이점만 주의하면 된다.
● Comparable은 타입을 인수로 받는 제네릭 인터페이스이다 : 메서드의 인수타입은 컴파일타임에 정해진다.
● compareTo 메서드는 필드의 동치가 아니라 순서를 비교한다.Comparable을 구현하지 않았다면, Comparator를 사용할 수 있다.
● compareTo 메서드 구현시 관계연산자 <, > 사용하는 방식은 거추장 스럽고 오류를 유발한다. [Java7]
// 아래 방법을 사용하자.
Integer.compare(a,b);
Float.compare(a,b);
Double.compare(a,b);
클래스의 핵심필드 여러개중 어떤것을 먼저 비교할 지에 대해 집중하라
● 비교자 생성 메서드(comparator construction method)와 팀을 꾸려 메서드 연쇄로 비교자를 생성. [Java 8]
private static final Comparator<PhoneNumber> COMPARATOR =
comparingInt((PhoneNumber pn)->pn.areaCode) // Comparator의 인스턴스 메서드
.thenComparingInt(pn -> pn.prefix) // 원하는 만큼 연달아 호출 가능
.thenComparingInt(pn -> pn.lineNumber);
public int compareTo(PhoneNumber pn){
return COMPARATOR.compare(this, pn);
}
이 람다에서 입력 인수의 타입을 명시해 주었다. (프로그램 컴파일을 도와준 것과 같다.)
● Comparator의 보조 생성 메서드
comparingLong, thenComparingLong
comparingDouble, thenComparingDouble
● 값의 차를 이용한 compareTo, compare 메서드를 사용하지 말자.
정수 오버플로 / 부동 소수점 계산 방식 오류
개선 : Integer.compare(a,b); || Comparator.comparingInt(x -> x.hashCode())
'Dev Book Review > Effective Java' 카테고리의 다른 글
[Effective Java] item 15. 클래스와 멤버의 접근 권한을 최소화하라 (1) | 2020.05.05 |
---|---|
[Effective Java] Chapter 3: 모든 객체의 공통 메서드 (0) | 2020.04.19 |
[Effective Java] item13. clone 재정의는 주의해서 진행하라 (0) | 2020.04.19 |
[Effective Java] Item12. toString을 항상 재정의하라 (2) | 2020.04.19 |
[Effective Java] item11. equals를 재정의하려거든 hashCode도 재정의하라 (0) | 2020.04.19 |