본문 바로가기

Java & JSP

[Java] 객체 정렬 - Comparable, Comparator

728x90
반응형

[Java] 객체 정렬 - Comparable, Comparator

 

들어가며

일반 숫자형은 정렬 기준이 정해져있다. 하지만 객체를 비교한다는 것은 사실상 주소값 비교가 아닌 객체가 갖고있는 속성의 값을 기준으로 해야한다. 그러므로 우리는 객체를 정렬하는 기준을 만들 수 있는 두 방법 Comparable, Comparator를 비교해보자.

 


Comparable

Comparable 인터페이스를 상속받아서 클래스의 기본 정렬 기준을 재정의 하는 방법이다.

public class Player implements Comparable<Player> {
    // Fields, Getters, Setters 생략

    @Override
    public int compareTo(Player o) {
        return o.getScore() - getScore();
    }
}

public class Main {
    public static void main(String[] args) {
        // Player 객체 여러 개 생성 생략

        Collections.sort(players);
        System.out.println(players); // [Player(name=Chloe, score=1090), Player(name=Eric, score=1018), Player(name=Bob, score=982), Player(name=Dale, score=982), Player(name=Alice, score=899)]
    }
}

compareTo의 정렬 기준

compareTo의 리턴 결과가 양수

-> compareTo 메서드를 부르는 객체가 더 크고, 파라미터로 들어온 o 객체가 더 작다고 판별된다.

-> 주체객체와 대상객체가 교체하여 정렬된다.

compareTo의 리턴 결과가 0

-> 두 객체의 값이 동일하다고 판별된다.

-> 정렬을 유지한다.

compareTo의 리턴 결과가 음수

-> compareTo 메서드를 부르는 객체가 더 작고, 파라미터로 들어온 o 객체가 더 크다고 판별된다.

-> 정렬을 유지한다.

위 예시에서는 내림차순 정렬을 구현하였다. 주체 객체의 score가 100, 파라미터 객체의 core가 150 이라고 가정해보자.

o.getScore() - getScore() = 150 - 100 = 50 > 0 --> 리턴 값이 양수

실제 score는 주체 객체가 더 작지만 리턴 값이 양수이므로 주체 객체가 크다고 판별된다. 그러므로 교체하여 정렬된다.

정렬 된 결과는 [150, 100] 이 된다. 내림차순 정렬이 잘 된 것을 볼 수 있다.

 

Collection.sort(객체)

사용 시 대상 객체가 정렬된다. 그 기준은 위에서 Comparable 인터페이스로 정의한 기준에 따라 정렬된다. 기본 데이터형과 달리 객체의 경우 정렬 기준을 정의하지 않으면 컴파일 에러가 난다.

 


Comparator

클래스 단위가 아닌 객체마다의 정렬 기준을 정의하는 방법이다.

정렬 대상의 클래스를 직접 수정할 수 없거나 정렬 대상 클래스의 정렬 기준이 있고 다른 정렬 기준이 필요한 경우 사용할 수 있다.

Comparator<Player> comparator = new Comparator<Player>() {
    @Override
    public int compare(Player a, Player b) {
        return b.getScore() - a.getScore();
    }
};

Collections.sort(players, comparator);
System.out.println(players); // [Player(name=Chloe, score=1090), Player(name=Eric, score=1018), Player(name=Bob, score=982), Player(name=Dale, score=982), Player(name=Alice, score=899)]

Comparator 인터페이스의 구현체를 만들고 Collection.sort()Array.sort() 메서드의 정렬 인자를 추가로 넘겨주면 된다.

compare의 정렬 기준은 위 정리된 내용과 동일하다.

 


람다 함수로 대체

Comparator 객체는 메서드가 하나뿐인 인터페이스를 구현하므로 람다 함수로 대체할 수 있다.

Collections.sort(players, (a, b) -> b.getScore() - a.getScore());
System.out.println(players); // [Player(name=Chloe, score=1090), Player(name=Eric, score=1018), Player(name=Bob, score=982), Player(name=Dale, score=982), Player(name=Alice, score=899)]

 

Stream으로 정렬

Stream을 사용할 경우 동일한 객체에 정렬되는게 아닌 새롭게 정렬된 객체를 생성할 수 있다.

Comparator 구현 객체를 sorted() 메서드의 인자로 받아서 정렬 기준을 적용한다.

List<Player> sortedPlayers = players.stream()
        .sorted((a, b) -> b.getScore() - a.getScore())
        .collect(Collectors.toList());
System.out.println(sortedPlayers); // [Player(name=Chloe, score=1090), Player(name=Eric, score=1018), Player(name=Bob, score=982), Player(name=Dale, score=982), Player(name=Alice, score=899)]

 


참고

https://www.daleseo.com/java-comparable-comparator/

 

[Java] 객체 정렬하기 1부 - Comparable vs Comparator

Engineering Blog by Dale Seo

www.daleseo.com

728x90
반응형