cleanUrl: /posts/what-you-consider-implements-comparable
share: true

Leecode 문제를 풀다가 Comparable 에 대한 정리가 필요한 순간이 왔다. Arrays.sort 를 사용하는데 어떻게 정렬하는지 조금 아리까리해서 이번 기회에 완전히 잡아야겠다는 생각이 들어 정리하게 되었다. 여기에 정리한 내용은 "Effective Java 14. Comparable을 구현할지 고민하라" 에서 필요한 부분만 발췌했다.

compareTo 는 Comparable 인터페이스에 유일하게 존재하는 method 이다.

interface Comaparable {
	int compareTo(T t);
}

String, Integer 와 같이 값을 갖는 모든 객체와 Enum 타입은 Comparable 을 구현했다.

Integer 클래스에서 구현한 Comparable

Integer 클래스에서 구현한 Comparable

compareTo 는 주어진 객체의 순서를 비교한다.

객체가 주어진 객체보다 작으면 음의 정수, 같으면 0, 크면 양의 정수를 반환한다. 따라서 다음의 test 가 통과한다 만약 비교할 수 없는 타입이 주어지면 ClassCastException 이 발생한다.

@Test
@DisplayName(value = 
	"compareTo 가 음수가 나오게 하자")
void compareToMinus() {
  Integer a = 1_000;
  Integer b = 2_000;
  assertThat(
		// 대상객체 a는 1000이고
		a.compareTo(b)
		// 주어진 객체 b는 2000이다.
		// 주어진 객체보다 작아 -1을 반환한다
	).isNegative();
  assertThat(
		a.compareTo(b)
	).isEqualTo(-1);
}
@Test
@DisplayName(value =
	"compareTo 가 양수가 나오게 하자")
void compareToPlus() {
  Integer a = 2_000;
  Integer b = 500;
  assertThat(
		// 대상객체는 2,000 이고
		a.compareTo(b)
		// 주어진 객체는 500 이다.
		// 주어진 객체보다 크기 때문에 1을 반환한다
	).isPositive();
  assertThat(
		a.compareTo(b)
	).isEqualTo(1);
}

eqauls 와 다음과 같은 내용이 매우 유사하다

(다음의 sgn 은 표현식이며 부호 함수를 의미한다 표현식이 음수, 0, 양수일때 -1, 0, 1을 반환한다)

  1. sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) 가 성립한다.
  2. 추이성을 보장한다
  3. 마찬가지로 x, y, z 에 대해
  4. 권고사항 (되도록 지키면 좋다)

compareTo 는 동치인지 비교하는게 아니라 그 순서를 비교한다.

만약 객체 참조의 필드를 비교하고자 한다면 재귀적으로 compareTo 를 호출해야 한다. 만약 Comparable 을 구현하지 않았다면 Compator 를 사용한다.

class PhoneNumber {
	public int compareTo(PhoneNumber pn) {
		int result = Short.comparable(areaCode, pn.areaCode); // 가장 먼저 비교할 필드
		if (result == 0) {
			result = Short.compare(prefix, pn.prefix); // 두번째로 비교할 필드
			if (result == 0) {
				result = Short.compare(lineNum, pn.lineNum); // 세번째로 비교할 필드
			}
		}
		return result;
	}
}

이 코드가 Java8 에 와서 굉장히 간지나게 변했다.