정렬3 - Comparable, Comparator

2024. 6. 23. 17:12김영한 Java/컬렉션 프레임워크

정렬은 배열 뿐만 아니라 순서가 있는 List 같은 자료 구조에도 사용할 수 있다.

 

List와 정렬

package collection.compare;

import java.util.LinkedList;
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 LinkedList<>();
        list.add(myUser1);
        list.add(myUser2);
        list.add(myUser3);
        System.out.println("기본 데이터");
        System.out.println(list);

        System.out.println("Comparable 기본 정렬");
        //Collections.sort(list)
        list.sort(null);
        System.out.println(list);

        System.out.println("IdComparator 정렬");
        list.sort(new IdComparator());
        System.out.println(list);

    }
}

 

실행 결과

기본 데이터
[MyUser{id='a', age=30}, MyUser{id='b', age=20}, MyUser{id='c', age=10}]
Comparable 기본 정렬
MyUser{id='b', age=20} vs MyUser{id='a', age=30}
MyUser{id='c', age=10} vs MyUser{id='b', age=20}
[MyUser{id='c', age=10}, MyUser{id='b', age=20}, MyUser{id='a', age=30}]
IdComparator 정렬
[MyUser{id='a', age=30}, MyUser{id='b', age=20}, MyUser{id='c', age=10}]

 

Collections.sort(list)

  • 리스트는 순서가 있는 컬렉션이므로 정렬할 수 있다.
  • 이 메서드를 사용하면 기본 정렬이 적용된다.
  • 하지만 이 방식 보다는 객체 스스로 정렬 메서드를 가지고 있는 list.sort() 사용을 더 권장한다.

list.sort(null)

  • 별도의 비교자가 없으므로 Comparable로 비교해서 정렬한다.
  • 자연적인 순서로 비교한다.
  • 자바 1.8부터 사용

Collections.sort(list, new IdComparator())

  • 별도의 비교자로 비교하고 싶다면 다음 인자에 비교자를 넘기면 된다.
  • 하지만 이 방식보다는 객체 스스로 정렬 메서드를 가지고 있는 list.sort()사용을 더 권장한다. 참고로 둘의 결과는 같다.

list.sort(new IdComparator())

  • 전달한 비교자로 비교한다.
  • 자바 1.8부터 사용

 

Tree구조와 정렬

TreeSet과 같은 이진 탐색 트리 구조는 데이터를 보관할 때, 데이터를 정렬하면서 보관한다. 따라서 정렬 기준을 제공하는 것이 필수다.

이진 탐색 트리는 데이터를 저장할 때 왼쪽 노드에 저장해야 할 지, 오른쪽 노드에 저장해야 할 지 비교가 필요하다.

따라서 TreeSet, TreeMap은 Comparable 또는 Comparator가 필수이다.

 

package collection.compare;

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);

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

 

실행 결과

Comparable 기본 정렬
[MyUser{id='c', age=10}, MyUser{id='b', age=20}, MyUser{id='a', age=30}]
IdComparator 사용
[MyUser{id='a', age=30}, MyUser{id='b', age=20}, MyUser{id='c', age=10}]

 

new TreeSet<>()
  • TreeSet을 생성할 때 별도의 비교자를 제공하지 않으면 객체가 구현한 Comporable을 사용한다.
new TreeSet<>(new IdComporator())
  • TreeSet을 생성할 때 별도의 비교자를 제공하면 Comparable 대신 비교자(Comparator)를 사용해서 정렬한다.

 

정리 

자바의 정렬 알고리즘은 매우 복잡하고, 또 거의 완성형에 가깝다.

자바는 개발자가 복잡한 정렬 알고리즘은 신경 쓰지 않으면서 정렬의 기준만 간단히 변경할 수 있도록, 정렬의 기준을 Comporable, Comparator 인터페이스를 통해 추상화해 두었다.

객체의 정렬이 필요한 경우 Comporable을 통해 기본 자연 순서를 제공하자. 자연 순서 외에 다른 정렬 기준이 추가로 필요하면 Comparator를 제공하자.