기타

Comparable 과 Comparator

ZzangHo 2022. 2. 23. 00:12
728x90

이번에 알아두면 좋을 것을 발견하여 이렇게 정리를 해본다.

 

기존에 배열을 정렬 할 경우

 

  • for문을 2번 돌린다
  • Arrays.sort를 사용
  • Stream API를 이용

보통 위의 3가지 방법으로 많이 사용하였는데 Comparator를 사용하여 정렬을 하는 방법을 알게 되었다.

 

일단 진행하기에 앞서 Comparable과 Comparator는 인터페이스(interface)이다. 이 말은 사용하려면 인터페이스 내에 선언된 메소드를 '반드시 구현'해야 한다.

 

comparable

 

comparator

 

각각 Java doc을 한번 보자

 

[Comparable]

https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html#method.summary

 

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

 

위의 문서를 보면 compareTo(T o) 메소드 하나가 선언되어 있는 것을 볼 수 있다. Comparable을 사용하려면 저 compareTo 메소드를 재정의 해주어야 한다.

 

[Comparator]

https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#method.summary

 

Comparator (Java Platform SE 8 )

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second. In the foregoing description, the notation sgn(expression) designates the mathematical s

docs.oracle.com

문서를 보면 많은 메소드들이 있지만 여기서 compare(T o1, T o2)메소드만 재정의 해주면 된다.

 

Comparable과 Comparator의 차이점

두 인터페이스 모두 객체를 비교할 수 있게 만들어 주는데 차이점이 있다.

차이점은 위의 메소드 형태를 보면 알 수 있는데 Comparable의 경우 compareTo 메소드의 경우 파라미터가 한 개 이고 Comparator의 경우 compare 메소드 파라미터는 두 개 이다.

 

왜 그럴까?

 

Comparable의 경우 자기 자신과 파라미터로 들어오는 대상(객체)를 비교하는 것이고, Comparator는 파라미터로 들어오는 두 대상(객체)를 비교하는 것이다. 비교를 한다는 액션으로 보았을 때는 같지만 비교 대상이 다르다

 

또 다른 차이점으로는 Compable의 경우 lang 패키지에 있기 때문에 import를 해줄 필요가 없지만 Comparator의 경우 util패키지에 있어서 import를 해주어야 한다.

 

실습

Comparable을 사용하여 두 객체를 비교해 보도록 하자.

User라는 클래스를 만들어 준 뒤에 Comparable를 implements받아 compare(T o)함수를 구현해 보자.

User는 다음과 같은 정보를 가지고 있다. 번호,이름,나이

나이 정보가 있으니 나이를 비교해 보자

public class ComparableTest {
    public static void main(String[] args) {
        User user1 = new User(1, "Lee", 10);
        User user2 = new User(2, "Kim", 15);

        int compare = user1.compareTo(user2);

        if (compare > 0) {
            System.out.println("user1이 나이가 더 많습니다.");
        } else if (compare == 0) {
            System.out.println("user1과 user2는 동갑입니다.");
        } else {
            System.out.println("user2이 나이가 더 많습니다.");
        }
    }
}

class User implements Comparable<User> {
    private int userId;
    private String userName;
    private int age;

    User(int userId, String userName, int age) {
        this.userId = userId;
        this.userName = userName;
        this.age = age;
    }


    @Override
    public int compareTo(User o) {
        if (this.age > o.age) {
            return 1;
        } else if (this.age == o.age) {
            return 0;
        } else {
            return -1;
        }
    }
}

위와 같이 양수,0,음수 형태로 많이 사용한다고 한다. (이게 정석인듯)

 

다음으로는 Comparator를 사용하여 두 객체를 비교해 보자

아래 코드를 보면 compare의 경우 2개의 파라미터를 받게 되어 있다. 

실제로는 user1의 메소드를 사용하였지만 user1은 영향을 주지 않는다. 파라미터로 넘어오는 2개의 객체 user2와 user3을 비교를 하기 때문이다. 

import java.util.Comparator;

public class ComparatorTest {
    public static void main(String[] args) {
        Person user1 = new Person(1, "Lee", 10);
        Person user2 = new Person(2, "Kim", 15);
        Person user3 = new Person(2, "You", 5);

        int compare = user1.compare(user2, user3);

        if (compare > 0) {
            System.out.println("user2이 나이가 더 많습니다.");
        } else if (compare == 0) {
            System.out.println("user2과 user3는 동갑입니다.");
        } else {
            System.out.println("user3이 나이가 더 많습니다.");
        }
    }
}

class Person implements Comparator<Person> {
    private int userId;
    private String userName;
    private int age;

    Person(int userId, String userName, int age) {
        this.userId = userId;
        this.userName = userName;
        this.age = age;
    }

    @Override
    public int compare(Person o1, Person o2) {
        if (o1.age > o2.age) {
            return 1;
        } else if (o1.age == o2.age) {
            return 0;
        } else {
            return -1;
        }
    }
}

 

위와 같이 테스트를 해보니 차이점을 더욱 명확히 알 수 있다.

 

이외에도 Arrays.sort에서도 Comparator를 사용할 수 있다.

아래 코드는 간략히 설명하면 String배열의 원소를 정렬하는 것이다.

이때 같은 배열의 서로 다른 원소를 비교할 때 사용도 많이 한다.

Arrays.sort(strings, new Comparator<String>(){
    @Override
    public int compare(String s1, String s2){
        if(s1.charAt(n) > s2.charAt(n)) return 1;
        else if(s1.charAt(n) == s2.charAt(n)) return s1.compareTo(s2);
        else if(s1.charAt(n) < s2.charAt(n)) return -1;
        else return 0;
    }
});

 

'기타' 카테고리의 다른 글

[자료구조] 이진 탐색 트리 (BST)  (0) 2022.04.15
Mac Os에 MariaDB 설치하기  (0) 2022.03.04
Java 제곱, 제곱근 구하는 방법  (0) 2022.02.22
3진법 구하기  (0) 2022.02.12
IntelliJ에서 Java실행이 되지 않을때?  (0) 2022.02.08