kotlin의 collection에서 정렬 기능을 제공하는 메서드는 무수히 많다. 이 메서드에 대해 하나씩 알아보자.
ex) sort(), sorted(), sortedBy{}, sortBy{}, sortedDescending(), sortedByDescending(), sortedWith()

기본적으로 sort() 메서드를 사용하면 오름차순 정렬이된다. 내림차순 정렬을 하고 싶으면 sortDescending() 메서드를 사용하면된다.

sort() VS sorted()

먼저 sort()sorted()의 차이를 알아보자.

이 둘의 차이는 기존의 배열을 건드리냐 아니냐의 차이가 있다. sort()는 기존의 배열을 오름차순으로 정렬한 것이다. 기존의 배열을 정렬했기에 반환타입은 Unit이 된다.

아래의 코드를 보면 이해가 갈 것이다.

fun main() {
    val arr1 = intArrayOf(1, 3, 4, 2, 5)
    val arr2 = intArrayOf(1, 3, 4, 2, 5)


    println("arr1: ${arr1.contentToString()}") // 1, 3, 4, 2, 5

    arr1.sort()

    println("arr1: ${arr1.contentToString()}") // 1, 2, 3, 4, 5

    val arr3 = arr2.sorted()
    println("arr2: ${arr2.contentToString()}") // 1, 3, 4, 2, 5
    println("arr3: ${arr3}") // 1, 2, 3, 4, 5
}


내림차순으로 정렬하고 싶은 경우 sortDescending()sortedDescending()를 사용해보자.

fun main() {
    val arr1 = intArrayOf(1, 3, 4, 2, 5)
    val arr2 = intArrayOf(1, 3, 4, 2, 5)

    println("arr1: ${arr1.contentToString()}") // 1, 3, 4, 2, 5

    arr1.sortDescending()

    println("arr1: ${arr1.contentToString()}") // 5, 4, 3, 2, 1

    val arr3 = arr2.sortedDescending()
    println("arr2: ${arr2.contentToString()}") // 1, 3, 4, 2, 5
    println("arr3: ${arr3}") // 5, 4, 3, 2, 1
}

sortBy{} VS sortedBy{}

sortBy{}는 기존 배열의 손대지 않고 기존 배열에서 정렬된 새로운 List를 반환한다.
sortedBy{}는 기존의 배열을 정렬히시키며 Unit을 반환한다.

sortBy{}sort()와 달리 특정 클래스나 컬렉션의 프로퍼티를 기준으로 정렬할 수 있다.

fun main() {
    val arr1 = arrayOf(
        Person("J", 25),
        Person("K", 20),
        Person("L", 22),
        Person("M", 21)
    )
    val arr2 = arrayOf(
        Person("J", 25),
        Person("K", 20),
        Person("L", 22),
        Person("M", 21)
    )


    println("arr1: ${arr1.contentToString()}")
    // Person(name=J, age=25), Person(name=K, age=20), Person(name=L, age=22), Person(name=M, age=21)

    arr1.sortBy { it.age } // age 프로퍼티를 기준으로 오름차순 정렬

    println("arr1: ${arr1.contentToString()}")
    // Person(name=K, age=20), Person(name=M, age=21), Person(name=L, age=22), Person(name=J, age=25)

    val arr3 = arr2.sortedBy { it.age }
    println("arr2: ${arr2.contentToString()}")
    // Person(name=J, age=25), Person(name=K, age=20), Person(name=L, age=22), Person(name=M, age=21)
    println("arr3: ${arr3}")
    // Person(name=K, age=20), Person(name=M, age=21), Person(name=L, age=22), Person(name=J, age=25)
}

위에서의 예제는 data class의 프로퍼티를 기준으로 정렬했지만 Map이나 Pair의 first나 second로도 정렬할 수 있다.
sortBy{} 또한 마찬가지로 내림차순 정렬을 하고 싶은 경우 sortByDescending(), sortedByDescending()를 사용하면 된다.

sortedWith()

만약 두 개 이상의 프로퍼티로 기준을 정해서 정렬을 하게 되는 경우 sortedWith()를 사용하게 된다. thenBy{}, thenByDescending{}를 이용해서 오름차순 또는 내림차순 정렬을 한다.
reversed() 메서드를 통해서 오름차순 정렬을 내림차순 정렬로 사용할 수 있다.

fun main() {
  val arr1 = arrayOf(
        Person("J", 25, 170),
        Person("K", 20, 160),
        Person("L", 22, 180),
        Person("M", 21, 174),
        Person("A", 21, 168)
    )

    println("arr1: ${arr1.contentToString()}")
    // Person(name=J, age=25), Person(name=K, age=20), Person(name=L, age=22), Person(name=M, age=21)

    val arr3 = arr1.sortedWith(compareBy { it.age })
    println("arr3: $arr3")
    // Person(name=K, age=20), Person(name=M, age=21), Person(name=A, age=21), Person(name=L, age=22), Person(name=J, age=25)

//  val arr4 = arr1.sortedWith(compareBy({it.age}, {it.name}))
    val arr4 = arr1.sortedWith(compareBy<Person>{it.age}.thenBy { it.name })
    println("arr4: $arr4")
    // Person(name=K, age=20), Person(name=A, age=21), Person(name=M, age=21), Person(name=L, age=22), Person(name=J, age=25)

    val arr5 = arr1.sortedWith(compareBy<Person>{it.age}.thenByDescending { it.height })
    val arr6 = arr1.sortedWith(compareBy({it.age}, { -it.height }))
    println("arr5: $arr5")
    // Person(name=K, age=20, height=160), Person(name=M, age=21, height=174), Person(name=A, age=21, height=168), Person(name=L, age=22, height=180), Person(name=J, age=25, height=170)
    println("arr6: $arr6")
    // Person(name=K, age=20, height=160), Person(name=M, age=21, height=174), Person(name=A, age=21, height=168), Person(name=L, age=22, height=180), Person(name=J, age=25, height=170)

    val arr7 = arr1.sortedWith(compareBy<Person>{it.age}.reversed().thenBy { it.height })
    println("arr7: $arr7")
}