Comprable, Comparator
Comparble과 Comparator는 JAVA에서 다양한 곳에 활용 되고 있다.
대표적으로 Heap(Priority Queue)자료구조가 있다. 이름도 비슷해서 헷갈릴 만한 두 인터페이스의 차이를 알아보자!
Comparble과 Comparator는 모두 인터페이스이므로 인터페이스 내 선언된 메서드를 반드시 구현해야 한다.
우선 두 인터페이스의 기본적인 구조를 알아보자
1. Comparable 인터페이스는 int 타입을 반환하는 compareTo(T o) 메서드를 가지고 있다.
2. Comparator 인터페이스는 선언된 메서드가 많다
우리가 객체 비교를 위해 구현해야 할 메서드는 compare(T o1, T o2) 이다.
즉, Comparable 인터페이스를 사용하기 위해선 compareTo를 구현해야하고...
Comparator 인터페이스를 사용하기 위해선 compare를 구현해야 한다.
이런 인터페이스를 구현하여 사용하는 가장 큰 이유는 ❓
"객체를 비교할 수 있도록 한다" 에 목적을 두고 있다.
자바의 primitive 타입의 경우 값을 부등호로 비교가 가능하지만, 객체를 값처럼 비교하기에는 기준이 모호하다.
public class Person {
int age;
int height;
public person(int age, int height) {
this.age = age;
this.height = height;
}
}
예시로 위의 클래스에서 객체를 생성한다면 어떤 사람은 나이로 비교하고 싶을 것이고 또 어떤 사람은 키로 비교하고 싶어할 수 있다. 또, 키가 같으면 나이가 많은 순으로 비교할래! 라는 사람도 있을 것이다.
두 인터페이스가 어떻게 객체를 비교하는지 알아보자.
비슷하면서도 다른 두 비교메서드 compareTo(T o) 와 compare(T o1, T o2) 의 차이점은 무엇일까?
짧게 정리해서 알아보면
1. 인자를 하나로 받는 compareTo(T o)는 필드에 있는 자기 자신과 매개변수 객체를 비교하는 것이다.
2. 인자를 두개로 받는 compare(T o1, T o2)는 자기 자신이 아닌 두 매개변수의 객체를 비교하는 것이다.
Comparable 인터페이스의 구조와 사용법 🔎
Java에서 Comparable 인터페이스를 들어가보면
과 같이 인터페이스명 뒤에<T> 타입을 정해주는 Generic을 사용하고 있다.
또 구현해야 할 메서드도 보인다.
어떻게 사용할까?
public class Person Implements Comparable<Person> {
int age;
int height;
public Person(int age, int height) {
this.age = age;
this.height = height;
}
@Override
public int compareTo(Person o) {
if (this.height > o.height ) return 1;
else if (this.height == o.height) return 0;
else return -1;
}
}
키를 기준으로 비교해 봤다.
어떤 기준으로 1(양수)과 0, -1(음수)을 반환할까?
> 자기 자신이 비교 대상보다 크다 - 양수 반환
> 자기 자신이 비교 대상과 같다 - 0 반환
> 자기 자신이 비교 대상보다 작다 - 음수 반환
@Override
public int compareTo(Person o) {
return this.height - o.height;
}
위 코드와 같이 하나의 계산식으로 세 개의 연산을 한번에 도출할 수 있다!
⚠️ 반드시 주의해야 할 점
메서드를 구현하기 전에 자료형의 범위를 파악해 보아야 한다. 예로 int 형의 범위는 -2³¹ ~ 2³¹-1 이다.
return Integr.MIN_VALUE - 1;
를 반환하면 주어진 범위의 상한선을 초과했기 때문에 Overflow가 발생한다.
따라서 연산을 하게 되면 2,147,483,647(양수)이 출력되기 때문에 비교에 오류가 발생할 수 있다!
자료형의 범위를 파악하여 Overflow를 방지하도록 하자
Comparator 인터페이스의 구조와 사용법 🔎
Comparator의 메서드 comapre(T o1, T o2)는 자기 자신이 아닌 두 매개변수 객체를 비교한다.
public class Person {
int age;
int height;
public Person (int age, int height) {
this.age = age;
this.height = height;
}
pubilc static void main(String[] args) {
Person[] people = new Person[10];
people[0] = new Person(13, 180);
people[1] = new Person(14, 160);
,
,
,
Arrays.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.age - p2.age;
}
});
}
}
마찬가지로 자료형의 범위를 꼭 파악하여 Overflow를 방지하자!!
대소 비교 🔎
compareTo 메서드와 compare 메서드 모두 음수, 0, 양수를 반환한다.
오름차순 기준으로
음수라는 말은 선행원소 < 후행원소 이므로 위치 교환이 일어나지 않는다.
양수라는 말은 선행원소 > 후행원소 이므로 위치 교환이 일어난다.
내림차순으로 비교하고 싶다면 ?
return -(this.height - o.height); // compareTo
return -(o1.height - o2.height); // comapre
반환 값의 부호를 반대로 설정해주자!
결론 📌
Java는 객체지향언어이기 때문에 객체의 비교를 정의하는 건 매우 중요하다.
많이 헷갈려할 수 있는 두 비교 인터페이스의 차이를 명확히 알고 있어야 한다.
아직 나도 차이를 완벽하게 이해한건 아니여서 더 공부해 볼 생각이다!
둘의 차이를 명확히 알고 적재적소에 잘 사용한다면 어떤 프로젝트를 하더라도 좋은 코드를 작성할 수 있을 것 같다.!
'JAVA' 카테고리의 다른 글
[JAVA] 자바의 default method (0) | 2025.02.24 |
---|