이 전글에서 보았던 Arrays.sort()와 Collection.sort() 메소드에는 공통적으로 Comparator를 추가적으로 인자로 받아들이는 메소드들이 있습니다.

public static <T> void sort(T[] a, Comparator<? super T> c)  <- Arrays 클래스에 있는 메소드

public static <T> void sort(List<T> list, Comparator<? super T> c) <- Collections 클래스에 있는 메소드.

sort를 할 때 보통은 Comparator는 주지 않고 정렬할 대상만을 전해 줍니다. 그렇게 전달 받은 대상의 타입이 Comparable 인터페이스를 구현하지 않았다면 컴파일 에러가 발생합니다. 이 부분은 Agile Java에도 나와 있지요.( Session 클래스가 Comparable 인터페이스를 구현하지 않은 채 Collection.sort(sessions) 와 같은 호출을 하여 에러가 발생하여 이 문제를 해결한 적이 있습니다.)

하지만 위의 방식대로 했을 때 발생할 수 있는 문제는.. 만약에 Student를 이름으로 정렬하지 않고 학번으로 정렬하고 싶다면 어떻게 하느냐 입니다. 즉 정렬을 하는 알고리즘만 살짝 바뀔 뿐인데 그렇다고 Comrable 인터페이스에 있는 comareTo() 메소드 안에 계속 if문을 심어 넣으면 변화에 닫혀있지 않는 코드가 되는 것입니다. 새로운 정렬 알고리즘은 추가 되고(확장에 열려있고 Opended) 소스코드의 변화는 최소화 하는(변화에 닫혀있는 Closed) OCP를 달성하려면  Strategy Pattern을 사용하여 문제를 해결 할 수도 있겠습니다. 그리고 이런한 문제를 엔터프라이즈 수업 과제로 다룬적이 있었습니다.

Comparator 인터페이스를 구현한 클래스들을 만들고 이것을 sort 메소드의 인자로 넘겨주면 Comparator의 compare 메소드를 사용하여 두 원소를 비교하게 됩니다.

Method Summary
int compare(T o1, T o2)
         Compares its two arguments for order.
boolean equals(Object obj)
         Indicates whether some other object is "equal to" this Comparator.

Comparator 인터페이스에 있는 메소드 입니다.

예를 들어 학생의 이름으로 정렬하는 Comparator를 만들고 싶다면 이 인터페이스를 구현하면 됩니다.

public class NameComparator implements Comparator<Student> {
   public int compare(Student s1, Student s2){
      return s1.getName().compareTo(s2.getName());
   }
}

이렇게 구현 해두고.. 이제 정렬을 할때

Collection.sort(students, NameComparator);

이렇게 호출을 하면 Student가 Comparable을 구현하고 compareTo에서 학번으로 비교를 한다고 해도 그 메소드는 무시되고 이름으로 정렬하게 됩니다.