본문 바로가기

Java & Kotlin

[Java] Comparable과 Comparator : 비교를 위한 인터페이스

✳️ Comparable 인터페이스 

Comparable은 자기 자신과 매개변수 객체를 비교할 수 있도록 만들어주는 인터페이스이다. 이 인터페이스를 채택하여 구현하면 compareTo메서드를 통하여 객체간에 비교가 가능해진다.

✳️ Comparable 인터페이스와 Comparator 인터페이스

Comparable과 비슷한 기능을 하는 인터페이스로 Comparator가 있다. 둘의 차이점은 다음과 같다.

1) 구현해야 하는 메서드의 차이

Comparable은 compareTo(T o1)을 구현해야 한다.

Comparator는 compare(T o1, T o2)를 구현해야 한다. 매개변수가 2개이다.

2) 사용 방법의 차이

Comparable은 자기 자신과 다른 객체를 비교한다.

Comparator는 매개변수로 들어오는 두 객체를 비교한다.

3) package

Comparable은 lang 패키지에 존재하기에, import를 하지 않아도 된다.

Comparator은 util 패키지에 있기에 따로 import를 해줘야 한다.

✳️ Comparable

Comparable은 아래와 같이 정의되어 있고, comparTo(T o) 메서드를 구현해주면 된다.

public interface Comparable<T> {
   public int compareTo(T o);
}

기본적으로 비교할 수 없는 타입을 비교할 수 있도록 만들어주는 것이고, 출력값으로 int가 나오기 때문에 T 자리에 비교하고자 하는 타입을 넣은 다음, 각 타입이 가진 멤버 변수들을 이용해 비교해주면 된다.

 

일반적인 구현 예시

class Person implements Comparable<Person> {
 
	private int age;			// 나이
	
	Person(int age) {
		this.age = age;
	}
	
	@Override
	public int compareTo(Person o) {
		if(this.age > o.age) {
			return 1;
		} else if(this.age == o.age) {
			return 0;
		}	else {
			return -1;
		}
	}
}

위와 같이 클래스가 가진 age 프로퍼티를 비교에 사용해줄 수 있다.

@Override	
public int compareTo(Person o) {
	return (this.age - o.age)
}

또는 이런 식의 방법도 가능하다. 어찌됐건 의도에 따라 양수, 0, 음수가 반환되기 때문이다.

이러한 방식을 사용할 때에는, Overflow와 Underflow만 조심해주면 된다.

 

Node<String>을 상속한 Genre의 비교

class Genre extends Node<String> implements Comparable<Genre> {

	public Genre(String name) {
		super(name);
	}
	
	@Override
	public int compareTo(Genre o) {
		return super.getItem().compareTo(o.getItem());
		// 스스로가 크면 1 같으면 0 작으면 -1
	}
}

SuperClass인 Node의 getItem()은 Node가 가진 item을 반환하는 메서드로, String이기에 String에 구현된 compareTo 메서드를 사용할 수 있다. 따라서 위와 같이 구현하는 것이 가능했다.

✳️ Comparator

class Person implements Comparator<Person> {
 
	private int age;			// 나이
	
	Person(int age) {
		this.age = age;
	}
	
	@Override
	public int compare(Person o1, Person o2) {
		return (o1.age - o2.age)
	}
}

Comparator는 위와 같이 구현해줄 수 있다.

 

앞서 Comparator의 compare은 매개변수로 온 두 객체를 비교한다고 했는데, 여기서 메서드의 호출은 a.compare(b, c) 와 같은 형식이 될 것이다. 따라서 메서드를 호출하는 주체는 결과에 영향을 주지 않는다는 것을 알 수 있다.

 

Comparator를 공부하면서, 보통의 경우 Comparable이 더 편리하겠다는 생각을 했다. 비교에 있어서 메서드 호출의 주체가 매번 변할 수 있는 Comparator은 일관성이 떨어지기 때문이다.

 

그러나 이러한 문제를 해결하기 위해 익명 객체를 이용할 수 있다고 한다.

 

익명 객체에 대한 이야기는 다음에 다루려고 한다.

 

[참고]

 

자바 [JAVA] - Comparable 과 Comparator의 이해

 

자바 [JAVA] - Comparable 과 Comparator의 이해

아마 이 글을 찾아 오신 분들 대개는 Comparable과 Comparator의 차이가 무엇인지 모르거나 궁금해서 찾아오셨을 것이다. 사실 알고보면 두 개는 그렇게 어렵지 않으나 아무래도 자바를 학습하면서 객

st-lab.tistory.com

Comparable (Java Platform SE 8 )

 

Comparable (Java Platform SE 8 )

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method. Lists (and arrays) of o

docs.oracle.com

Comparator (Java Platform SE 8 )