Comparator과 Comparable의 필요성
정렬을 하기 위해서는 '기준'이 필요합니다.
기본적으로 int, double 과 같은 primitive 타입의 변수는 자연스럽게 대소 관계가 존재하기 때문에 정렬 기준을 쉽게 설정할 수 있습니다. 예를 들어, 1 < 2 이므로 오름차순 정렬에서는 1, 2 순서로 정렬됩니다.
하지만 객체는 정렬 기준이 자동으로 존재하지 않습니다. 예를 들어, 아래와 같은 Person 클래스를 정의했다고 가정해보았습니다.
public class Person{
int age;
int phoneNumber;
public Person(int age, int phoneNumber){
this.age = age;
this.phoneNumber = phoneNumber;
}
}
Person p1 = new Person(10, 1111);
Person p2 = new Person(20, 2222);
위의 Person 객체들을 어떻게 정렬할까요? 나이(age) 를 기준으로 할것인가, 전화번호(phoneNumber)를 기준으로 할것인가? 이때 필요한 것이 Compartor , Comparable 입니다. 이 두 인터페이스는 객체를 비교할 수 있는 기준을 정의하는 역할을 합니다.
Comparable 과 Comparator 의 공통점과 차이점
Comparable 과 Comparator 는 모두 인터페이스로, 객체 간의 비교를 가능하게 해줍니다. 각 인터페이스는 추상 메소드를 정의하고 있으며, 이를 구현하여 비교 기준을 명시할 수 있습니다.
Comparble 인터페이스
Comparable 인터페이스는 객체의 기본 정렬 기준을 정의할 때 사용합니다. java.lang 패키지에 포함되어 있으며, compareTo 메서드를 구현해야 합니다.
public interface Comparable<T>{
int compareTo(T o);
}
- 예를 들어, Person 클래스에서 나이(age) 를 기준으로 정렬하려면 다음과 같이 Comparable 을 구현할 수 있습니다.
public Person implements Comparable<Person>{
int age;
int phoneNumber;
public Person(int age, int phoneNumber){
this.age = age;
this.phoneNumber = phoneNumber;
}
@Override
public int compareTo(Person p){
return this.age - p.age;
}
}
여기서 compareTo 메서드는 자기 자신의 age 필드 (this.age) 와 매개 변수 객체의 age 필드(p.age) 를 비교하여 정렬합니다.
Compartor 인터페이스
Comparator 인터페이스는 기본 정렬 기준 외에 다른 기준으로 정렬하고자 할 때 사용합니다. java.util 패키지에 포함되어 있으며, compare 메서드를 구현해야 합니다.
public interface Comparator<T> {
int compare(T o1, T o2);
}
예를 들어, Person 클래스를 정렬하고 싶다면 Compartor 를 구현할 수 있습니다.
public class Person implements Comparator<Person>{
int age;
int phoneNumber;
public Person(int age, int phoneNumber){
this.age = age;
this.phoneNumber = phoneNumber;
}
@Override
public int compare(Person p1, Person p2){
return p1.age - p2.age;
}
}
여기서 compare 메서드는 두 객체 p1과 p2의 나이를 비교하여 정렬합니다.
자바 정렬의 기본 원리
자바는 기본적으로 오름차순으로 정렬을 수행합니다. compare 혹은 compareTo 메서드가 반환하는 값에 따라 정렬 기준이 결정됩니다.
a-b > 0 인 경우, 선행하는 원소가 후행하는 원소보다 큰 상태 즉 내림차순이므로 원소를 바꿉니다.
a-b < 0 인 경우, 선행하는 원소가 후행하는 원소보다 작은 상태 즉 오름차순이므로 원소를 바꾸지 않습니다.
정리하자면,
compare/compareTo 메서드 값이 양수일 경우 원소를 바꿉니다.
compare/compareTo 메서드 값이 음수일 경우 원소를 바꾸지 않습니다.
만약 내림차순으로 정렬을 하고 싶은 경우는 반환 값을 조정해주면 됩니다.
return b-a;
return (a-b) * -1;
Comparator의 익명 객체(클래스)를 활용
Comparator를 통해 compare 메소드를 사용하기 위해서는 compare 메소드를 활용하기 위한 객체(comp)가 필요합니다.
public class Test {
public static void main(String[] args) {
Person a = new Person(10, 1111);
Person b = new Person(20, 2222);
Person c = new Person(30, 3333);
Person comp = new Person(0, 0); //비교만 할 객체
int isBig = comp.compare(a, b);
int isBig2 = comp.compare(b, c);
int isBig3 = comp.compare(a, c);
}
}
하지만 Comparator 기능만 따로 두고 싶다면 "익명 객체(이름이 정의되지 않은 객체)"를 사용하여 구현할 수도 있습니다. 즉, 이름은 정의되지 않았지만 Comparator 를 구현하는 익명 객체 (comp1) 를 생성하도록 하겠습니다.
public class Test {
public static void main(String[] args) {
Comparator<Person> comp1 = new Comparator<Person>(){
@Override
public int compare(Person p1, Person p2){
return p1.age - p2.age;
}
};
}
}
이렇게 하면 외부에서 Compartor 를 구현하는 익명 객체를 생성하여 필요한 정렬 기준을 사용할 수 있습니다.
출처
'Language > Java' 카테고리의 다른 글
[Java] 배열을 정렬해보겠습니다. (0) | 2023.09.13 |
---|---|
[Java] Queue 인터페이스 (0) | 2023.07.05 |
[Java] Stack 클래스 (0) | 2023.07.05 |
[Java] Set 인터페이스 (0) | 2023.05.15 |
[Java] List<E> 인터페이스 (0) | 2023.05.15 |