자바에서는 정렬하는 방법이 여러가지가 있고, 특히 좀 복잡한 정렬이 필요한 경우에는 어렵기도 하다... 따라서 이에 대해 잘 알아둘 필요가 있다.
Arrays.sort()로 int 배열을 인자로 전달하면 오름차순으로 정렬됩니다.
int[] arr = {1, 26, 17, 25, 99, 44, 303};
Arrays.sort(arr);
System.out.println("Sorted arr[] : " + Arrays.toString(arr)); // [1, 17, 25, 26, 44, 99, 303]
내림차순 정렬이 필요한 경우, sort()의 인자에 추가로 Collections.reverseOrder()를 전달해야 합니다. 참고로, Collections.reverseOrder()는 Comparator 객체이다. Comparator는 직접 구현할 수 있지만, 미리 정의된 Collections 함수를 사용하는 것이다.
Arrays.sort(arr, Collections.reverseOrder());
내림차순 Comparator를 직접 구현하려면 다음과 같이 할 수 있습니다.
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
return i2 - i1;
}
});
위 코드는 Lambda를 사용하여 이렇게 더 짧게 구현할 수 있습니다. 이 방식이 최고인듯??
Arrays.sort(arr, (i1, i2) -> i2 - i1);
리스트 같은 컬렉션을 정렬할 때는 Collections.sort()를 사용할 수 있다.
List<String> list = new LinkedList<String>();
list.add(“김철수”);
list.add(“김영희”);
Collections.sort(list);
내림차순 정렬은 더 쉬운 편이다. reverse() 라는게 따로 있다.
Collections.reverse(list);
아니면 마찬가지로 이렇게도 가능하다.
Collections.sort(list, Collections.reverseOrder());
참고로, 리스트 같은 경우는 자체 sort 메서드가 있다. 따라서 굳이 Collections.sort()를 사용하지 않아도 된다. Java 8 이후에 생겼다고 함.
List<String> list = new LinkedList<String>();
list.add(“김철수”);
list.add(“김영희”);
list.sort();
자바 정렬을 제대로 이해하려면 Comparable와 Comparator을 알아야 한다. 그리고... 객체 정렬 같이 복잡한 정렬이 필요한 경우도 이 개념에 대해 알고 있어야 된다.
Comparable과 Comparator는 모두 인터페이스(interface)라는 것이다. 즉, Comparable 혹은 Comparator을 사용하고자 한다면 인터페이스 내에 선언된 메소드를 '반드시 구현'해야한다는 것이다.
우선 Comparator부터 살펴보자. Comparator이 더 자주 사용되는거 같아서...
Comparator 인터페이스를 쓰려면 compare 메서드를 구현해야 한다. 특히, Comparator를 사용할때는 익명 객체(클래스)를 활용한다. 익명 객체는 쉽게 말해서 '이름이 정의되지 않은 객체'를 의미한다.
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer i1, Integer i2) {
return i2 - i1;
}
});
이를 객체 정렬에 적용하면 다음과 같이 사용할 수 있다. 아래는 Student 객체에 학급에 대한 프로퍼티로 정렬을 하는 예시이다.
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
list.add(new Student(12, 1));
list.add(new Student(13, 3));
list.add(new Student(11, 2));
Comparator<Student> StudentClassNumberComp = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.classNumber - o2.classNumber;
}
};
Collections.sort(list, StudentClassNumberComp);
}
}
// 외부에서 익명 객체로 Comparator가 생성되기 때문에 클래스에서 Comparator을 구현 할 필요가 없어진다.
class Student {
int age; // 나이
int classNumber; // 학급
Student(int age, int classNumber) {
this.age = age;
this.classNumber = classNumber;
}
}
Comparable 인터페이스를 쓰려면 compareTo 메소드를 구현해야한다. Comparable의 compareTo(T o) 메소드는 파라미터(매개변수)가 한 개이고, Comparator의 compare(T o1, T o2) 메소드는 파라미터가 두개라는 차이가 있다.
왜 이렇게 구분되는걸까? Comparable은 "자기 자신과 매개변수 객체를 비교"하는 것이고, Comparator는 "두 매개변수 객체를 비교"한다는 것이다. 즉, 본질적으로 비교한다는 것 자체는 같지만, 비교 대상이 다르다는 것이다. 또 다른 차이점이라면 Comparable은 lang패키지에 있기 때문에 import 를 해줄 필요가 없지만, Comparator는 util패키지에 있다.
class Student implements Comparable<Student> {
int age; // 나이
int classNumber; // 학급
Student(int age, int classNumber) {
this.age = age;
this.classNumber = classNumber;
}
@Override
public int compareTo(Student o) {
/*
* 만약 자신의 age가 o의 age보다 크다면 양수가 반환 될 것이고,
* 같다면 0을, 작다면 음수를 반환할 것이다.
*/
return this.age - o.age;
}
}
그러면 이를 sort하면 자동으로 해당 compareTo 정의에 따라 sort가 된다.
ArrayList<Student> list = new ArrayList<>();
list.add(new Student(12, 1));
list.add(new Student(13, 3));
list.add(new Student(11, 2));
Collections.sort(list);