일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 프리미티브 타입
- 합병 정렬
- 제네릭 와일드 카드
- Study Halle
- junit 5
- 정렬
- 스파르타코딩클럽
- 상속
- System.err
- 함수형 인터페이스
- raw 타입
- 제네릭 타입
- docker
- System.out
- 로컬 클래스
- 자바스터디
- 항해99
- 자바할래
- auto.create.topics.enable
- 람다식
- 접근지시자
- annotation processor
- 브릿지 메소드
- System.in
- yield
- 바운디드 타입
- Switch Expressions
- throwable
- github api
- 익명 클래스
- Today
- Total
코딩하는 털보
이펙티브 자바, 아이템 14. Comparable을 구현할지 고려하라 본문
이펙티브 자바, 아이템 14. Comparable을 구현할지 고려하라
Comparable 인터페이스의 compareTo를 구현하여 사용하는 것을 고려해 볼 수 있다.
compareTo 메서드는 Object의 equals와 두 가지 차이가 있다.
- 단순 동치성 비교에 더해 순서까지 비교할 수 있다.
Comparable을 구현했다는 것은 인스턴스들에 자연적인 순서가 있음을 뜻한다.
알파벳, 숫자, 연대 처럼 순서가 명확한 값 클래스를 작성한다면 반드시 Comparable 인터페이스를 구현하자.
compareTo 규약을 지키지 못하면 비교를 활용하는 클래스와 어울리지 못한다. (ex. TreeSet, TreeMap 또는 Collections와 Arrays의 정렬)
compareTo 메서드로 수행하는 동치성 검사도 equals 규약과 같이 반사성, 대칭성, 추이성을 충족해야 한다. - 제네릭
equals 는 인수의 타입을 확인하거나 형변환하는 작업이 필요했지만 Comparable이 제네릭 인터페이스이므로 compareTo에서는 그런 작업이 필요하지 않다.
객체 참조 필드를 비교할때는 compareTo 메서드를 재귀적으로 호출한다. Comparable 인터에이스를 구현하지 않은 필드나 표준이 아닌 순서로 비교하려면 비교자(Comparator)를 대신 사용한다.
참고사항
compareTo 메서드에서 관계 연산자 '<'와 '>'를 사용하는 이전 방식은 거추장스럽고 오류를 유발하니, 추천하지 않는다. 자바 7부터 박싱된 기본 타입 클래스들에 compare 정적 메서드가 추가되었다.
핵심 필드의 비교 순서는 가장 핵심적인 것 부터.
자바 8부터 Comparator 인터페이스가 일련의 비교자 생성 메서드와 팀을 꾸려 메서드 연쇄 방식으로 비교자를 생성할 수 있다. 코드는 깔끔하지만 성능적으로는 좋지 않다고 한다.
private static final Comparator<PhoneNumber> COMPARATOR = Comparator.comparingInt((PhoneNumber pn) -> pn.ariaCode) .thenComparingInt((PhoneNumber pn) -> pn.prefix) .thenComparingInt((PhoneNumber pn) -> pn.lineNum); @Override public int compareTo(PhoneNumber pn) { return COMPARATOR.compare(this, pn); }
Comparator는 comparingInt, thenComparingInt 등 숫자용 기본 타입을 커버하는 보조 생성 메서드를 가지고 있다.
그리고 comparing 정적 메서드와 thenComparing 메서드는 객체 참조용 비교자 생성 메서드이다.해시코드 값의 차(
o1.hashCode() - o2.hashCode()
)를 기준으로 비교하면 정수 오버플로를 일으키거나 부동소수점 계산 방식에 따른 오류를 낼 수 있다.
대신Integer.compare(o1.hashCode(), o2.hashCode())
또는 Comparator가 제공하는 비교자 생성 메서드를 활용Comparator.comparingInt(o -> o.hashCode())