[//]: # (title: Ordering) The order of elements is an important aspect of certain collection types. For example, two lists of the same elements are not equal if their elements are ordered differently. In Kotlin, the orders of objects can be defined in several ways. First, there is _natural_ order. It is defined for implementations of the [`Comparable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-comparable/index.html) interface. Natural order is used for sorting them when no other order is specified. Most built-in types are comparable: * Numeric types use the traditional numerical order: `1` is greater than `0`; `-3.4f` is greater than `-5f`, and so on. * `Char` and `String` use the [lexicographical order](https://en.wikipedia.org/wiki/Lexicographical_order): `b` is greater than `a`; `world` is greater than `hello`. To define a natural order for a user-defined type, make the type an implementer of `Comparable`. This requires implementing the `compareTo()` function. `compareTo()` must take another object of the same type as an argument and return an integer value showing which object is greater: * Positive values show that the receiver object is greater. * Negative values show that it's less than the argument. * Zero shows that the objects are equal. Below is a class for ordering versions that consist of the major and the minor part. ```kotlin class Version(val major: Int, val minor: Int): Comparable { override fun compareTo(other: Version): Int = when { this.major != other.major -> this.major compareTo other.major // compareTo() in the infix form this.minor != other.minor -> this.minor compareTo other.minor else -> 0 } } fun main() { println(Version(1, 2) > Version(1, 3)) println(Version(2, 0) > Version(1, 5)) } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.6"} _Custom_ orders let you sort instances of any type in a way you like. Particularly, you can define an order for non-comparable objects or define an order other than natural for a comparable type. To define a custom order for a type, create a [`Comparator`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-comparator/index.html) for it. `Comparator` contains the `compare()` function: it takes two instances of a class and returns the integer result of the comparison between them. The result is interpreted in the same way as the result of a `compareTo()` as is described above. ```kotlin fun main() { //sampleStart val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length } println(listOf("aaa", "bb", "c").sortedWith(lengthComparator)) //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} Having the `lengthComparator`, you are able to arrange strings by their length instead of the default lexicographical order. A shorter way to define a `Comparator` is the [`compareBy()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.comparisons/compare-by.html) function from the standard library. `compareBy()` takes a lambda function that produces a `Comparable` value from an instance and defines the custom order as the natural order of the produced values. With `compareBy()`, the length comparator from the example above looks like this: ```kotlin fun main() { //sampleStart println(listOf("aaa", "bb", "c").sortedWith(compareBy { it.length })) //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} You can also define an order based on multiple criteria. For example, to sort strings by their length and alphabetically when the lengths are equal, you can write: ```kotlin fun main() { //sampleStart val sortedStrings = listOf("aaa", "bb", "c", "b", "a", "aa", "ccc") .sortedWith { a, b -> when (val compareLengths = a.length.compareTo(b.length)) { 0 -> a.compareTo(b) else -> compareLengths } } println(sortedStrings) // [a, b, c, aa, bb, aaa, ccc] //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} Since sorting by multiple criteria is a common scenario, the Kotlin standard library provides the [`.thenBy()`](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.comparisons/then-by.html) function that you can use to add a secondary sorting rule. For example, you can combine `compareBy()` with `.thenBy()` to sort strings by their length first and alphabetically second, just like in the previous example: ```kotlin fun main() { //sampleStart val sortedStrings = listOf("aaa", "bb", "c", "b", "a", "aa", "ccc") .sortedWith(compareBy { it.length }.thenBy { it }) println(sortedStrings) // [a, b, c, aa, bb, aaa, ccc] //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} The Kotlin collections package provides functions for sorting collections in natural, custom, and even random orders. On this page, we'll describe sorting functions that apply to [read-only](collections-overview.md#collection-types) collections. These functions return their result as a new collection containing the elements of the original collection in the requested order. To learn about functions for sorting [mutable](collections-overview.md#collection-types) collections in place, see the [List-specific operations](list-operations.md#sort). ## Natural order The basic functions [`.sorted()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sorted.html) and [`.sortedDescending()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sorted-descending.html) return elements of a collection sorted into ascending and descending sequence according to their natural order. These functions apply to collections of `Comparable` elements. ```kotlin fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") println("Sorted ascending: ${numbers.sorted()}") println("Sorted descending: ${numbers.sortedDescending()}") //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} ## Custom orders For sorting in custom orders or sorting non-comparable objects, there are the functions [`.sortedBy()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sorted-by.html) and [`.sortedByDescending()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sorted-by-descending.html). They take a selector function that maps collection elements to `Comparable` values and sort the collection in natural order of that values. ```kotlin fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") val sortedNumbers = numbers.sortedBy { it.length } println("Sorted by length ascending: $sortedNumbers") val sortedByLast = numbers.sortedByDescending { it.last() } println("Sorted by the last letter descending: $sortedByLast") //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} To define a custom order for the collection sorting, you can provide your own `Comparator`. To do this, call the [`.sortedWith()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sorted-with.html) extension function passing in your `Comparator`. With this function, sorting strings by their length looks like this: ```kotlin fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") println("Sorted by length ascending: ${numbers.sortedWith(compareBy { it.length })}") //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} ## Check sorted order You can use the following extension functions to check whether elements already follow a specified order: * `.isSorted()` * `.isSortedDescending()` * `.isSortedWith(comparator)` * `.isSortedBy(selector)` * `.isSortedByDescending(selector)` These extension functions return `true` if the elements are in the specified order or if there are fewer than two elements. They return `false` and stop checking as soon as they find an out-of-order pair. For collections without a guaranteed iteration order, such as `HashSet`, the result may vary across calls. The same applies to sequences that don't produce elements in a consistent order. To get the same result across calls, use these functions only on collections with a guaranteed iteration order, such as `List`. When checking `Double` and `Float` values, these functions treat `NaN` as greater than any other value and `-0.0` as less than `0.0`. Additionally, the `.isSortedBy()` and `.isSortedByDescending()` functions treat `null` selector results as less than any non-null value. When you call these functions on a sequence, the operation is terminal. It consumes the sequence to produce a `Boolean` value instead of returning another sequence. > These sorted-order functions are also available for arrays, primitive arrays, and unsigned arrays. > Unsigned arrays and operations on them are [Experimental](components-stability.md#stability-levels-explained) and require opt-in with the `@ExperimentalUnsignedTypes` annotation. > {style="note"} Here's an example of checking sorted order with the `.isSorted()` and `.isSortedBy()` functions: ```kotlin data class User(val name: String, val age: Int) fun main() { //sampleStart val numbers = listOf(1, 2, 3, 4) println(numbers.isSorted()) // true val users = listOf( User("Alice", 24), User("Bob", 31), User("Charlie", 29), ) println(users.isSortedBy(User::age)) // false val descending = listOf(4, 3, 2, 1) println(descending.isSortedDescending()) // true //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="2.4"} ## Reverse order You can retrieve the collection in the reversed order using the [`.reversed()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/reversed.html) function. ```kotlin fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") println(numbers.reversed()) //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} The `.reversed()` extension function returns a new collection with the copies of the elements. So, if you change the original collection later, this won't affect the previously obtained results of `.reversed()`. Another reversing function - [`.asReversed()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/as-reversed.html) - returns a reversed view of the same collection instance, so it may be more lightweight and preferable than `.reversed()` if the original list is not going to change. ```kotlin fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") val reversedNumbers = numbers.asReversed() println(reversedNumbers) //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} If the original list is mutable, all its changes reflect in its reversed views and vice versa. ```kotlin fun main() { //sampleStart val numbers = mutableListOf("one", "two", "three", "four") val reversedNumbers = numbers.asReversed() println(reversedNumbers) numbers.add("five") println(reversedNumbers) //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"} However, if the mutability of the list is unknown or the source is not a list at all, `.reversed()` is more preferable since its result is a copy that won't change in the future. ## Random order Finally, there is a function that returns a new `List` containing the collection elements in a random order - [`.shuffled()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/shuffled.html). You can call it without arguments or with a [`Random`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.random/-random/index.html) object. ```kotlin fun main() { //sampleStart val numbers = listOf("one", "two", "three", "four") println(numbers.shuffled()) //sampleEnd } ``` {kotlin-runnable="true" kotlin-min-compiler-version="1.3"}