자바에는 정렬을 도와주는 인터페이스인 Comparable, Comparator 가 있습니다.Collection 을 통해 정렬을 간편히 수행할 수 있는 데, Comparable 이나 Comparator 를 구현하는 구현체이거나 람다를 이용하여 정렬방법을 구현해야 합니다.
primitive 타입 배열과 같은 것들은 자연스러운 순서로 정렬이 됩니다.(Arrays.sort 는 DualPivotQuicksort 라는 알고리즘을 사용합니다.)
Comparable
Comparable 은 일반적으로 생각할 수 있는 정렬을 정의할 때 구현하는 인터페이스입니다. (물론, 꼭 그럴 이유는 없습니다만 JavaDoc 의 주석으로 되어있으므로, 일반적인 용례를 생각하면 그에 따르는 것이 혼란을 줄일 수 있습니다.)
Comparable 을 구현하면 compareTo 를 구현해야 합니다.
public class Compare implements Comparable<Compare> {
private int number;
public Compare(int number) {
this.number = number;
}
@Override
public int compareTo(Compare o) {
return o.number - number;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Compare compare = (Compare)o;
return number == compare.number;
}
@Override
public int hashCode() {
return Objects.hash(number);
}
}
@Test
@DisplayName("Comparable 을 구현한 객체의 정렬")
void sort_object() {
List<Compare> compares = IntStream.range(0, 10)
.mapToObj(Compare::new).collect(toList());
List<Compare> expected = new ArrayList<>();
for (int i = 9; i >= 0; i--) {
expected.add(new Compare(i));
}
Collections.sort(compares);
assertEquals(expected, compares);
}
예시를 들기위해 수의 크기에 따른 내림차순 정렬로 구현하였습니다.
Comparable 을 구현하지 않은 클래스를 Arrays 나 Collections 의 sort 메서드로 정렬하려고 하면 ClassCastException 이 발생합니다.
@Test
@DisplayName("Comparable 을 구현하지 않은 객체는 예외 발생")
void sort_object_exception() {
assertThrows(ClassCastException.class,
() -> Arrays.sort(IntStream.range(0, 10)
.mapToObj(NotCompare::new).toArray()));
}
Comparator
Comparator 는 명시적인 정렬을 하고 싶을 때 사용하는 인터페이스입니다.
compare 메서드를 구현함으로써 정렬을 정의합니다. 클래스에 정의하는 것보다는 정렬시 함수로 넘기는 것을 더 선호합니다(개인적인 의견입니다)
@Test
@DisplayName("comparator 통해 정렬")
void sort_comparator_implements() {
List<Integer> numbers = Arrays.asList(3, 9, -1, 7, 6);
List<Integer> expected = Arrays.asList(9, 7, 6, 3, -1);
// comparator 를 람다로 구현하여 넘겨주었음
numbers.sort((n1, n2) -> n2 - n1);
assertEquals(expected, numbers);
}
Comparator 를 람다로 정의할 때, 여러 조건을 넘기도록 구현할 수 있습니다.
@Test
@DisplayName("함수를 통해 정렬조건을 여러개 넣기")
void sort_thenComparing() {
List<Person> people = Arrays.asList(
new Person(10, "bcd"),
new Person(12, "csb"),
new Person(10, "abc")
);
List<Person> expected = Arrays.asList(
new Person(10, "abc"),
new Person(10, "bcd"),
new Person(12, "csb")
);
// thenComparing 을 통해 조건을 이어감
people.sort(Comparator.comparing(Person::getAge).thenComparing(Person::getName));
assertEquals(expected, people);
}
해당 테스트코드는 github 에 수록되어있습니다.
'Java' 카테고리의 다른 글
EnumMap 살펴보기 (0) | 2021.01.05 |
---|---|
PriorityQueue 살펴보기 (0) | 2021.01.04 |
resource file 읽기 (0) | 2018.12.18 |
eclipse task tag 사용(TODO) (0) | 2018.12.18 |
java applicaiton logback 설정 (0) | 2018.12.18 |