이번에는 Comparable 인터페이스의 compareTo() 이다.
compareTo() 함수에는 "문자열의 비교" 와 "숫자의 비교" 두 방식이 존재한다.
숫자의 비교 같은 경우는 단순히 크다(1), 같다(0), 작다(-1) 의 관한 결과값을 리턴해주는 반면
문자열의 비교 같은 경우는 같다(0) 외엔 문자열의 아스키 코드 값의 차이를 리턴한다.
compareTo는 단순 동치성 비교에 더해 순서까지 비교할 수 있고 제네릭하다.
Complarable을 구현했다는 것은 그 클래스의 인스턴스들에는 자연적은 순서가 있음을 뜻한다.
그래서 Comparable을 구현한 객체들의 배열은 다음처럼 손쉽게 정렬할 수 있다.
Arrays.sort(a);
검색, 극단값 계산, 자동 정렬되는 컬렉션 관리도 역시 쉽게 할 수 있다.
예컨대 다음 프로그램은 명령줄 인수들을 알파벳순으로 출력한다.
public class WordList {
public static void main(String[] args) {
Set<String> s = new TreeSet<>();
Collections.addAll(s, args);
System.out.println(s);
}
String이 Comparable을 구현한 덕분이다.
Comparable을 구현하여 이 인터페이스를 활용하는 수많은 제네릭 알고리즘과 컬렉션의 힘을 누릴 수 있다.
사실상 자바 플랫폼 라이브러리의 모든 값 클래스와 열거타입이 Comparable을 구현했다.
알파벳, 숫자, 연대 같이 순서가 명확한 값 클래스를 작성한다면 반드시 Comparable 인터페이스를 구현하자.
CompareTo 메서드 규약
이 객체와 주어진 객체의 순서를 비교한다.
이 객체가 주어진 객체보다 작으면 음의 정수를, 같으면 0을, 크면 양의 정수로 반환한다.
이 객체와 비교할 수 없는 타입의 객체가 주어지면 ClassCastException을 던진다.
다음 설명에서 sgn(표현식) 표기는 수학에서 말하는 부호 함수(signum function)를 뜻하며,
표현식의 값이 음수, 0, 양수일 때 -1, 0, 1을 반환하도록 정의했다.
- Comparable을 구현한 클래스는 모든 x, y에 대해 sgn(x.compartTo(y)) == -sgn.(y.compareTo(x))여야 한다(따라서 x.compareTo(y)는 y.compareTo(x)가 예외를 던질때에 한해 예외를 던져야 한다).
- Comparable을 구현한 클래스는 추이성을 보장해야 한다. 즉, (x.compareTo(y) > 0 && y.compareTo(z) > 0)이면 x.compareTo(z) > 0이다.
- Comparable을 구현한 클래스는 모든 z에 대해 x.compareTo(y) == 0이면 sgn(x.compareTo(z)) == sgn(y.compareTo(z))다.
- 이번 권고가 필수는 아니지만 꼭 지키는 게 좋다. (x.compareTo(y) == 0) == (x.equals(y))여야 한다. Comparable을 구현하고 이 권고를 지키지 않는 모든 클래스는 그 사실을 명시해야 한다. 다음과 같이 명시하면 적당할 것이다.
"주의 : 이 클래스의 순서는 equals 메서드와 일관되지 않다."
첫 번째 규약은 두 객체 참조의 순서를 바꿔 비교해도 예상한 결과가 나와야 한다는 것이다.
두 번째 규약은 첫 번째가 두 번째보다 크고 두 번째가 세 번째보다 크면, 첫 번째는 세 번째보다 커야한다는 것이다.
세 번째 규약은 크기가 같은 객체들끼리는 어떤 객체와 비교해도 항상 같아야 한다는 것이다.
이 세가지 규약은 equals규약과 같이 반사성, 대칭성, 추이성을 충족해야 한다는 것이다.
그래서 주의사항도 같다.
순서를 고려해야 하는 값 클래스를 작성한다면 꼭 Comparable 인터페이스를 구현하여, 그 인스턴스들을 쉽게 정렬하고, 검색하고,
비교 기능을 제공하는 컬렉션과 어우러지도록 해야 한다.
'JAVA > 이펙티브 자바' 카테고리의 다른 글
16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 (0) | 2023.07.01 |
---|---|
15. 클래스와 멤버의 접근 권한을 최소화하라 (0) | 2023.07.01 |
13. clone 재정의는 주의해서 진행하라 (0) | 2023.07.01 |
12. toString을 항상 재정의하라 (0) | 2023.07.01 |
11. equals를 재정의하려거든 hashCode도 재정의하라 (0) | 2023.07.01 |