본문 바로가기
JAVA/기본

Comparator 구현

by 히포파타마스 2022. 8. 11.

Comparator 구현

 

자바의 대부분의 Collection이나 자료구조는 자료를 정렬할 수 있는 sort()와 같은 메서드들을 갖고 있다.

그런데 sort()와 같은 메서드는 자료를 비교하기 위해 함수형 인터페이스인 Comparator를 요구하곤한다.

 

[Arrays의 sort()]

 

[Stream의 sorted()]

 

 

특히 자바의 기본형이 아닌 객체간 비교를 하는 경우에는, 객체간 비교 방법을 Comparator로 명시해주어야 한다.

따라서 코딩을 하다보면 Comparator를 구현해야 할 순간이 반드시 온다. 

 

Comparator를 구현하는 것 자체는 그렇게 어렵지 않다. 

그러나 항상 부등호 방향과 음수, 양수 중 어떤식으로 반환했을 때 오름차순, 내림차순이 되는지 맨날 헷갈렸기에 이에 대해 한번 제대로 정리해 보겠다.

 

 

 

 

1. Comparator 구현

다음과 같은 User 클래스가 있다고 하자.

 

[User]

public static class User{
    public String name;
    public int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

 

 

 

다음과 같은 반복문으로 User를 생성하여 UserList에 넣어준다.

 

[userList 생성]

ArrayList<User> userList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    userList.add(new User("testUser" + i, i));
}

 

 

이 userList의 User들을 나이순으로 정렬하고 싶다면 List의 sort() 메서드를 사용 할 수 있다.

이 때 sort() 메서드는 User를 비교할 Comparator를 요구한다.

 

sort()에 넘길 Comparator는 다음과 같이 구현할 수 있다.

 

[Comparator 구현]

userList.sort((user1, user2) -> user1.age > user2.age ? -1 : 1);

 

중요한건 정렬 방법의 표현이다.

위 예시에서 구현한 Comparator는 앞의 user의 나이가 더 크면 -1(음수)을 반환한다.

 

Comparator를 사용하는 정렬 메서드는 Comparator가 음수를 반환하면 비교된 두 수를 바꾸지 않는다.

위의 예에서 앞의 user가 더 클 때 음수가 반환되고 두 수는 바뀌지 않는다.

따라서 User 나이의 내림차순으로 정렬이 된다.

 

 

 

 

 

 

2. Comparator 메서드

특별한 방법으로 객체를 비교한다면 직접 Comparator를 구현해야하지만, 단순히 객체의 필드값(기본형)을 비교할 때는 Comparator의 comparing 메서드를 사용하면 된다.

 

 

다음은 userList를 User의 이름순으로 오름차순으로 정렬하는 예시이다.

 

[comparaing 사용 예]

userList.sort(Comparator.comparing(User::getName));

comparing은 Funtion 타입의 함수형 인터페이스를 매개변수로 받는다.

따라서 필드값을 반환하는 메서드를 참조형태로 사용해서 넣어줄 수 있다.

 

 

 

역순으로 정렬하고 싶다면 뒤에 reversed를 붙여주면 된다.

 

[comparing 내림차순 정렬]

userList.sort(Comparator.comparing(User::getName).reversed());

 

 

 

 

2.1 기본형 비교 메서드

만약 비교 대상이 기본형이라면 Comparator가 제공하는 static 메서드를 사용해서 손쉽게 Comparator를 만들 수 있다.

 

User의 나이가 담긴 collect를 정렬할 때 다음과 같이 Comparator의 static 메서드를 사용할 수 있다.

 

[naturalOrder]

collect.sort(Comparator.naturalOrder());

 

오름차순으로 정렬한다.

 

 

 

[reverseOrder]

collect.sort(Comparator.reverseOrder());

 

내림차순으로 정렬한다.

 

 

 

 

 

3. 객체에 Comparable 구현

객체에 Comparable을 구현해 놓으면 sort() 메서드를 사용할 때 요구하는 매개변수에 따라 Comparator를 구현하지 않아도 된다.

 

[Comparable 구현]

public static class User implements Comparable<User>{
    public String name;
    public int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int compareTo(User user) {
        return this.age > user.age ? -1 : 1;
    }
}

 

Comparable은 Comparator와 달리 매개변수가 하나이다.

때문에 비교대상은 객체자기 자신과 매개변수가 된다.

Comparable도 역시 음수를 반환할 때 비교되는 두 객체를 바꾸지 않는다.

 

따라서 위와 같이 Comparable을 구현하면 내림 차순으로 정렬이 되게 된다.

 

 

 

[Collections.sort()]

Collections.sort(userList);

 

Collections의 sort() 메서드는 객체에 Comparable이 정의 되지 않았다면 Comparator를 요구한다.

이 경우는 User에 Comparable이 구현되어있기 때문에 Comparator를 구현하지 않아도 내림차순으로 정렬된다.

 

 

 

'JAVA > 기본' 카테고리의 다른 글

자료구조 초기화, List-Array 변환  (0) 2022.07.15
스트림(Stream)  (0) 2021.12.08
Optional  (0) 2021.12.03
람다(Lambda)  (0) 2021.11.28
예외 처리(exception handling)  (0) 2021.08.02

댓글