1. Collection Sort
Kotlin 에서는 Collection 을 정렬하기 위한 여러가지 유틸리티들을 제공합니다.
1.1. Sort, Sorted
가장 쉬운 방법은 sort
메소드를 호출하는 겁니다.
기본적으로 오름차순으로 정렬합니다.
val list = mutableListOf(1, 2, 7, 6, 5, 6)
list.sort()
println(list) // [1, 2, 5, 6, 6, 7]
sort
메소드는 해당 Collection 의 원소 위치가 변경됩니다.
기존 Collection 은 그대로 둔 채 새로운 Collection 으로 받길 원한다면 sorted
메소드를 사용해야 합니다.
sorted
메소드를 사용하면 기존 Collection 은 변하지 않습니다.
val list = mutableListOf(1, 2, 7, 6, 5, 6)
val sorted = list.sorted()
println(sorted) // [1, 2, 5, 6, 6, 7]
println(list) // [1, 2, 7, 6, 5, 6] (sorted 를 사용했기 때문에 변하지 않음)
내림차순으로 정렬하고 싶다면 sortByDescending
를 사용하거나 reverse
메소드를 사용하면 됩니다.
마찬가지로 sortedByDescending
를 사용하면 원래 Collection 의 변경 없이 내림차순으로 정렬된 값을 구할 수 있습니다.
// 1. sortByDescending 로 내림차순 정렬
list.sortByDescending { it }
val sorted = list.sortedByDescending { it }
// 2. reverse 사용해서 정렬 후 뒤집기
list.sort()
list.reverse()
val sorted = list.sorted().reversed()
1.2. SortBy
만약 Object 의 특정 Property 들을 기준으로 정렬하고 싶다면 sortBy
메소드를 사용하면 됩니다.
sortBy
메소드는 Object 를 받아서 Property 를 반환하는 Lamdba 식을 파라미터로 받습니다.
val list = mutableListOf(1 to "a", 2 to "b", 7 to "c", 6 to "d", 5 to "c", 6 to "e")
list.sortBy { it.second }
println(list) // [(1, a), (2, b), (7, c), (5, c), (6, d), (6, e)]
sort
와 마찬가지로 기존 Collection 의 변경 없이 정렬된 값을 받고 싶다면 sortedBy
를 사용하면 됩니다.
그리고 내림차순을 지원하는 sortByDescending
도 있습니다.
1.3. SortWith
sortWith
메소드를 사용하면 여러 가지 조건을 섞어서 정렬할 수 있습니다.
sortWith
메소드는 Comparator
를 파라미터로 받습니다.
(Kotlin 에서 Comparator
를 생성하는 여러가지 방법은 다음 챕터에서 다룹니다)
val list = mutableListOf(1 to "a", 2 to "b", 7 to "c", 6 to "d", 5 to "c", 6 to "e")
list.sortWith(compareBy({it.second}, {it.first}))
println(list) // [(1, a), (2, b), (5, c), (7, c), (6, d), (6, e)]
위 Collection 은 it.second
(문자) 로 먼저 정렬된 후에 it.first
(숫자) 로 정렬됩니다.
그리고 역시 sortedWith
메소드가 존재하며, 역순으로 정렬할때는 reverse
를 사용하거나 Comparator
를 반대로 수정하면 됩니다.
2. Comparison
Kotlin 은 Comparator
를 만들기 위해 kotlin.comparisons
라는 유용한 패키지를 제공합니다.
이 챕터에서는 아래 컨텐츠를 다룹니다.
- Comparator creation
- Handling of null values
- Comparator rules extension
2.1. Comparator Creation
Kotlin 은 Comparator
를 생성하는 여러 팩토리 메서드를 제공합니다.
2.1.1. naturalOrder
가장 간단한 생성 메서드는 naturalOrder()
입니다.
아무런 파라미터를 필요로 하지 않으며 오름차순을 기본으로 합니다.
val ascComparator = naturalOrder<Long>()
2.1.2. compareBy
여러 개의 속성을 사용하고 싶다면 compareBy
메소드를 사용하면 됩니다.
파라미터로는 Comparable
를 리턴하는 정렬 규칙을 여러 개 사용할 수 있습니다.
그럼 넘겨진 규칙들은 순차적으로 호출 되며 원소들을 정렬합니다.
만약 먼저 나온 규칙에서 원소의 우열이 가려져 정렬 처리가 되었다면 뒤의 규칙들은 확인하지 않습니다.
val complexComparator = compareBy<Pair<Int, String?>>({it.first}, {it.second})
위 코드에서 it.first
값을 사용해 먼저 비교를 하고 값이 같은 경우에만 it.second
비교까지 이루어집니다.
2.1.3. Comparator
간단하게 new Comparator
를 선언해서 만들 수도 있습니다.
자바와 마찬가지로 두 원소에 대한 비교 조건을 넣어줘야 합니다.
val caomparator = Comparator<Int> { a, b -> a.compareTo(b) }
2.2. Handling of null Values
정렬하려는 Collection 이 null
값을 갖고 있을 수도 있습니다.
nullsFirst
또는 nullsLast
와 함께 Comparator
를 사용하면 null
값을 가장 처음 또는 가장 마지막에 위치하도록 설정할 수 있습니다.
val list = mutableListOf(4, null, 1, -2, 3)
list.sortWith(nullsFirst()) // [null, -2, 1, 3, 4]
list.sortWith(nullsLast()) // [-2, 1, 3, 4, null]
list.sortWith(nullsFirst(reverseOrder())) // [null, 4, 3, 1, -2]
list.sortWith(nullsLast(compareBy { it })) // [-2, 1, 3, 4, null]
2.3. Comparator Rules Extension
Comparator
오브젝트는 추가적인 정렬 규칙과 혼합되거나 확장할 수 있습니다.
kotlin.comparable
패키지에 있는 then
키워드를 활용하면 됩니다.
첫 번째 비교의 결과가 동일할 때만 두번째 비교가 이루어집니다.
val students = mutableListOf(21 to "Helen", 21 to "Tom", 20 to "Jim")
val ageComparator = compareBy<Pair<Int, String?>> {it.first}
val ageAndNameComparator = ageComparator.thenByDescending {it.second}
// [(20, Jim), (21, Tom), (21, Helen)]
println(students.sortedWith(ageAndNameComparator))
위 코드는 나이가 어린 순으로 먼저 정렬하고 나이가 같으면 이름을 알파벳 역순으로 정렬합니다.
Reference
'Language > Kotlin' 카테고리의 다른 글
Kotlin Collections 와 Sequences 의 차이점 (feat. Java Stream) (1) | 2022.01.27 |
---|---|
Kotlin Enum (0) | 2021.10.06 |
[Kotlin] Swap (0) | 2020.11.11 |
[Kotlin] For 문 (0) | 2020.11.11 |
[Kotlin] String - drop, dropLast, dropWhile, dropLastWhile (0) | 2020.09.25 |