본문 바로가기
Language/Java

[Java API] Comparable, Comparator 인터페이스

by 클레어몬트 2024. 10. 25.

Java에서 객체의 정렬을 구현할 때 주로 사용하는 두 가지 인터페이스인 Comparable과 Comparator에 대해 알아보겠다. 이 두 인터페이스는 컬렉션의 정렬 기준을 정의하는 데 중요한 역할을 하며, 각각의 특성과 사용법을 이해하는 것이 필요하다.

 

1. Comparable 인터페이스

Comparable 인터페이스는 객체 자체에 기본 정렬 순서를 정의할 때 사용된다. 이 인터페이스를 구현하면, 해당 객체는 기본적인 정렬 기준을 가지게 되며, Collections.sort() 또는 Arrays.sort() 메서드를 사용할 때 자동으로 이 기준을 따르게 된다.

 

[주요 메서드]

- int compareTo(T o) : 현재 객체와 매개변수로 전달된 객체를 비교하여 순서를 결정하는 메서드이다. 이 메서드는 세 가지 값을 반환할 수 있다.

  • -(음수값): 현재 객체가 매개변수 객체보다 작음을 의미
  • 0: 현재 객체와 매개변수 객체가 같음을 의미
  • +(양수값): 현재 객체가 매개변수 객체보다 큼을 의미
package collection.compare;

public class MyUser implements Comparable<MyUser> {
    private String id;
    private int age;

    public MyUser(String id, int age) {
        this.id = id;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public int getAge() {
        return age;
    }

    @Override // 정렬의 기준을 age로 정했다 (나이 오름차순)
    public int compareTo(MyUser o) {
        return (this.age < o.age) ? -1 : ((this.age == o.age) ? 0 : 1);
    }

    @Override
    public String toString() {
        return "MyUser{" +
                "id='" + id + '\'' +
                ", age=" + age +
                '}';
    }
}

 

2. Comparator 인터페이스

Comparator 인터페이스는 "객체"의 정렬 기준을 외부에서 정의할 때 사용된다. 이 인터페이스를 구현하면, 동일한 객체라도 다양한 정렬 기준을 가질 수 있으며, 필요에 따라 다른 기준으로 정렬할 수 있다.

 

[주요 메서드]

- int compare(T o1, T o2) : 두 객체를 비교하여 순서를 결정하는 메서드이다. 이 메서드는 Comparable의 compareTo 메서드와 유사하게 음수값, 0, 양수값을 반환한다.

- boolean equals(Object obj) : (선택적) 두 Comparator가 동일한지 비교하는 메서드이다.

package collection.compare;

import java.util.Comparator;

public class IdComparator implements Comparator<MyUser> {
    @Override
    public int compare(MyUser o1, MyUser o2) {
        return o1.getId().compareTo(o2.getId());
    }
}

 

 

(테스트 메인 코드)

package collection.compare;

import java.util.Arrays;

public class SortMain3 {
    public static void main(String[] args) {
        MyUser myUser1 = new MyUser("a", 30);
        MyUser myUser2 = new MyUser("b", 20);
        MyUser myUser3 = new MyUser("c", 10);

        MyUser[] array = {myUser1, myUser2, myUser3};
        System.out.println("기본 데이터");
        System.out.println(Arrays.toString(array));
        System.out.println();
        System.out.println("Comparable 기본 정렬");
        Arrays.sort(array);
        System.out.println(Arrays.toString(array));

        // 추가 (id 기준 정렬)
        System.out.println();
        System.out.println("IdComparator 정렬");
        Arrays.sort(array, new IdComparator());
        System.out.println(Arrays.toString(array));
        System.out.println("IdComparator.reversed() 정렬");
        Arrays.sort(array, new IdComparator().reversed());
        System.out.println(Arrays.toString(array));
    }
}

 

 

+ Collection 자료구조에도 적용할 수 있다

(List 테스트 코드)

package collection.compare;

import java.util.ArrayList;
import java.util.List;

public class SortMain4 {
    public static void main(String[] args) {
        MyUser myUser1 = new MyUser("a", 30);
        MyUser myUser2 = new MyUser("b", 20);
        MyUser myUser3 = new MyUser("c", 10);

        List<MyUser> list = new ArrayList<>();
        list.add(myUser1);
        list.add(myUser2);
        list.add(myUser3);
        System.out.println("기본 데이터");
        System.out.println(list + "\n");

        System.out.println("Comparable 기본 정렬");
        list.sort(null); // 객체 스스로의 정렬 메서드를 갖고 있는 list.sort()를 추천
        // Collections.sort(list); - 비추천
        System.out.println(list + "\n");

        System.out.println("IdComparator 정렬");
        list.sort(new IdComparator()); // 객체 스스로의 정렬 메서드를 갖고 있는 list.sort()를 추천
        // Collections.sort(list) - 비추천
        System.out.println(list);

        System.out.println("IdComparator reversed 정렬");
        list.sort(new IdComparator().reversed()); // 객체 스스로의 정렬 메서드를 갖고 있는 list.sort()를 추천
        // Collections.sort(list) - 비추천
        System.out.println(list);
    }
}

list.sort()를 더 추천하는 이유는 객체가 이미 내 데이터를 갖고 있기 때문에 내 걸 가지고 내가 정렬한다는 게 조금 더 객체지향적이기 때문

 

 

(TreeSet 테스트 코드)

package collection.compare;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

public class SortMain5 {
    public static void main(String[] args) {
        MyUser myUser1 = new MyUser("a", 30);
        MyUser myUser2 = new MyUser("b", 20);
        MyUser myUser3 = new MyUser("c", 10);

        TreeSet<MyUser> treeSet1 = new TreeSet<>();
        treeSet1.add(myUser1);
        treeSet1.add(myUser2);
        treeSet1.add(myUser3);
        System.out.println("Comparable 기본 정렬");
        System.out.println(treeSet1);
        System.out.println();

        TreeSet<MyUser> treeSet2 = new TreeSet<>(new IdComparator());
        treeSet2.add(myUser1);
        treeSet2.add(myUser2);
        treeSet2.add(myUser3);
        System.out.println("IdComparator 정렬");
        System.out.println(treeSet2);

        TreeSet<MyUser> treeSet3 = new TreeSet<>(new IdComparator().reversed());
        treeSet3.add(myUser1);
        treeSet3.add(myUser2);
        treeSet3.add(myUser3);
        System.out.println("IdComparator reversed 정렬");
        System.out.println(treeSet3);
    }
}

 

 

 

[Comparable vs Comparator]

 

 

 

 

 

 

 

 

※ 람다 표현식을 사용한 Comparator

Java 8 이후, Comparator 인터페이스는 람다 표현식을 사용하여 더 간결하게 구현할 수가 있다.

package collection.compare;

import java.util.Arrays;

public class SortMain3 {
    public static void main(String[] args) {
        MyUser myUser1 = new MyUser("a", 30);
        MyUser myUser2 = new MyUser("b", 20);
        MyUser myUser3 = new MyUser("c", 10);

        MyUser[] array = {myUser1, myUser2, myUser3};
        System.out.println("기본 데이터");
        System.out.println(Arrays.toString(array));
        System.out.println();

        System.out.println("Comparable 기본 정렬");
        Arrays.sort(array);
        System.out.println(Arrays.toString(array));

        // 추가 (id 기준 정렬)
        System.out.println();
        System.out.println("IdComparator 정렬 (람다 표현식 사용)");
        Arrays.sort(array, (user1, user2) -> user1.getId().compareTo(user2.getId()));
        System.out.println(Arrays.toString(array));

        System.out.println();
        System.out.println("IdComparator.reversed() 정렬 (람다 표현식 사용)");
        Arrays.sort(array, (user1, user2) -> user2.getId().compareTo(user1.getId()));
        System.out.println(Arrays.toString(array));
    }
}

ps 문제를 풀 때 요긴하게 사용할 수 있다