상세 컨텐츠

본문 제목

[이펙티브 자바] Item 14. Comparable을 구현할지 고려하라 | 3장

카테고리 없음

by yooputer 2023. 9. 15. 08:44

본문

Comparable을 구현해야하는 이유

  • Comparable을 구현했다는 것은 그 클래스의 인스턴스에 자연적인 순서가 있음을 뜻한다.
  • Comparable을 구현하여 수많은 제네릭 알고리즘과 컬렉션을 이용할 수 있다.
  • 알파벳, 숫자, 연대 같이 순서가 명확한 값 클래스를 작성한다면 반드시 Comparable을 구현하는 것이 좋다.

 

Comparable 메서드 일반 규약

  1. 첫번째 객체가 두번째 객체보다 작으면, 두번째 객체가 첫번째 객체보다 커야하고
    첫번째 객체와 두번째 객체가 같으면, 두번째 객체와 첫번째 객체가 같아야 하고,
    첫번째 객체가 두번째 객체보다 크면, 두번째 객체는 첫번째 객체보다 작아야한다.
  2. 첫번째 객체가 두번째 객체보다 크고, 두번째 객체가 세번째 객체보다 크면 첫번째 객체는 세번째 객체보다 크다.
  3. 크기가 같은 객체는 어떤 객체와 비교해도 항상 같아야 한다.

 

Comparable 주의사항

  • Comparable을 구현한 클래스를 확장하여 새로운 컴포넌트를 추가했다면 compareTo규약을 지킬 수 없다.
    확장하는 대신 독립된 클래스를 만들고 확장하려고 했던 클래스를 참조하는 필드를 두자.
  • compareTo 메서드 결과와 equals 메서드 결과가 같아야한다. 
    • 정렬된 컬렉션들은 equals대신 compareTo를 사용하기 때문이다

 

CompareTo 메서드 작성 요령

  • 인수타입이 컴파일할 때 정해지기 때문에 타입을 확인하거나 형변환할 필요가 없다.
  • null을 넣어 호출하면 NullPointerException을 던져야 한다
  • 객체 참조 필드를 비교하려면 compareTo를 재귀적으로 호출해야 한다. 
  • Comparable을 구현하지 않은 필드나 표준이 아닌 순서로 비교해야한다면 Comparator을 대신 사용한다
  • 핵심 필드 먼저 비교하고, 비교결과가 0이 아니라면 그 즉시 반환한다.

 

Compare

  • 자바7부터는 박싱된 기본타입 클래스를 비교할 때 compare를 이용하면 된다. 

 

Comparator

  • 자바8부터는 메서드 연쇄 방식으로 비교자르 생성할 수 있게 되었다.(하지만 약간의 성능 저하가 있다)
  • comparingInt, thenComparingInt 등의 보조 생성 메서드가 존재한다. 
  • 객체 참조용 비교자 생성 메서드인 comparing, thenComparing이 존재한다
// Comparator 메서드 체이닝 방식
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);
}