How do you sort a List in Kotlin, and what is the difference between sorted(), sortedBy { }, and sortedDescending()?
answer
- sorted* returns a new List, never mutates
- sorted() needs Comparable (natural order)
- sortedBy { } sorts by an extracted key
- Descending: sortedDescending / sortedByDescending
- sort() (no 'ed') mutates a MutableList in place
basics
~20 sUse sorted() to order items from low to high. Use sortedBy { } to sort by a chosen property. Use sortedDescending() for high to low. All three return a new list and leave the original unchanged.
solid answer
~40 sOn a read-only List, sorted() returns a new List ordered by the elements' natural ordering (they must be Comparable, like Int or String). sortedBy { selector } returns a new List ordered by a key you extract per element, e.g. people.sortedBy { it.age }; the selector's result must be Comparable. sortedDescending() reverses natural order, and sortedByDescending { } reverses by a selector. None of these mutate the receiver — they always allocate and return a fresh List. This contrasts with sort()/sortBy() on a MutableList, which reorder in place and return Unit. For custom multi-key logic use sortedWith(comparator). Sorting is stable: equal elements keep their original relative order.
code
kotlin · 7 linesval nums = listOf(3, 1, 2)
println(nums.sorted()) // [1, 2, 3], nums unchanged
println(nums.sortedDescending()) // [3, 2, 1]
val words = listOf("banana", "fig", "apple")
println(words.sortedBy { it.length }) // [fig, apple, banana]
println(words.sortedByDescending { it.length }) // [banana, apple, fig]go deeper
Knows sorted/sortedBy/sortedDescending exist and return a new list ordered as named.
Explains the Comparable requirement, stability, and that sortedBy builds a comparator from a selector.
Contrasts sorted* (copy) with sort* (in-place), discusses stability guarantees and when to reach for sortedWith.
Reasons about allocation cost of copying vs in-place, stability as an API contract callers depend on, and library-API ergonomics of selector-based vs comparator-based overloads.
## Natural ordering and Comparable Kotlin's `sorted()` orders elements by their **natural ordering**, defined by the `Comparable<T>` interface and its `compareTo` method. Types like `Int`, `Long`, `String`, and `Char` implement `Comparable`, so `listOf(3,1,2).sorted()` gives `[1,2,3]`. Calling `sorted()` on a list whose elements are not `Comparable` is a compile error. ## The non-mutating sorted* family These extension functions on `Iterable`/`Array` all **return a new `List`** and never change the receiver: - `sorted()` — ascending natural order. - `sortedDescending()` — descending natural order. - `sortedBy { selector }` — ascending by a key extracted from each element; the key must be `Comparable`. - `sortedByDescending { selector }` — descending by that key. - `sortedWith(comparator)` — order by an explicit `Comparator`. ```kotlin data class Person(val name: String, val age: Int) val people = listOf(Person("Ann", 30), Person("Bo", 22)) val byAge = people.sortedBy { it.age } // [Bo, Ann] val byAgeDesc = people.sortedByDescending { it.age } // [Ann, Bo] val names = listOf("c","a","b").sorted() // [a, b, c] // 'people' is unchanged after all of the above ``` ## sortedBy vs sortedWith `sortedBy { it.age }` is shorthand; under the hood it builds a `Comparator` via `compareBy`. Use `sortedWith` when you need multiple keys or custom comparison (`sortedWith(compareBy({ it.lastName }, { it.firstName }))`). ## Stability Kotlin's sort is **stable**: elements that compare equal keep their original relative order. This matters when sorting by a single key — ties stay in input order. ## Don't confuse with in-place sort `sort()`, `sortBy { }`, `sortDescending()` exist only on `MutableList` (and arrays), reorder elements **in place**, and return `Unit`. Use the `sorted*` family for read-only lists or when you must preserve the original.
- What happens if you call sorted() on a List<SomeType> where SomeType isn't Comparable?It won't compile — sorted() is only available when the element type implements Comparable. You must use sortedBy/sortedWith with a comparator instead.
- Does sortedBy mutate the original list?No. The entire sorted* family returns a new List and leaves the receiver untouched; only sort*/sortBy on MutableList mutate.
sorted() is like photocopying your contacts and alphabetizing the copy; sort() is rewriting the original list in place.
saying these in an interview costs you the question
- Claiming sorted() sorts the list in place
- Thinking sortedBy mutates the original collection
- Believing sorted() works on any type without Comparable
- Confusing sorted() (returns List) with sort() (returns Unit)