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 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: 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.
class Version(val major: Int, val minor: Int): Comparable
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 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.
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() 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:
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. 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 in place, see the List-specific operations.
Natural order
The basic functions sorted() and sortedDescending() return elements of a collection sorted into ascending and descending sequence according to their natural order. These functions apply to collections of Comparable elements.
Custom orders
For sorting in custom orders or sorting non-comparable objects, there are the functions sortedBy() and sortedByDescending() . They take a selector function that maps collection elements to Comparable values and sort the collection in natural order of that values.
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 >
To define a custom order for the collection sorting, you can provide your own Comparator . To do this, call the sortedWith() function passing in your Comparator . With this function, sorting strings by their length looks like this:
Reverse order
You can retrieve the collection in the reversed order using the reversed() function.
reversed() 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()
- 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.
If the original list is mutable, all its changes reflect in its reversed views and vice versa.
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() . You can call it without arguments or with a Random object.
Сортировка коллекций
Для некоторых типов коллекций является важным аспектом то, как упорядочены их элементы. Например, два списка с одинаковыми элементами не равны, если их элементы упорядочены по-разному.
В Kotlin порядок объектов можно задать несколькими способами.
Во-первых, существует естественный порядок (ориг. natural order). Он характерен для наследников интерфейса Comparable . Если не был указан другой порядок сортировки, то они будут отсортированы в естественном порядке.
Большинство встроенных типов являются Comparable :
- Числовые типы используют традиционный числовой порядок: 1 больше, чем 0 ; -3.4f больше, чем -5f и т.д.
- Char и String используют лексикографический порядок: b больше, чем a ; world больше, чем hello .
Таким образом, чтобы ваш собственный класс при сортировке использовал естественный порядок, сделайте его наследником Comparable . Дополнительно потребуется реализовать функцию compareTo() . В качестве аргумента она должна принимать другой объект такого же типа, а возвращать целое число, указывающее, какой из объектов больше:
- Положительное значение показывает, что объект-приёмник больше аргумента.
- Отрицательное значение показывает, что объект-приёмник меньше аргумента.
- Ноль показывает, что объекты равны.
В примере ниже показан класс для сортировки версий, состоящий из переменных major и minor .
class Version(val major: Int, val minor: Int): Comparable < override fun compareTo(other: Version): Int < if (this.major != other.major) < return this.major - other.major >else if (this.minor != other.minor) < return this.minor - other.minor >else return 0 > > fun main() < println(Version(1, 2) >Version(1, 3)) // false println(Version(2, 0) > Version(1, 5)) // true >
Пользовательский порядок (ориг. custom order) позволяет вам сортировать экземпляры любого типа так, как вам нравится. В частности, вы можете определить порядок для сортировки объектов, не являющихся наследниками Comparable , а также задать Comparable типам порядок, отличный от естественного. Осуществляется это при помощи Comparator . У Comparator есть функция compare() , которая принимает два объекта, а в качестве результата сравнения возвращает целое число. Результат интерпретируется так же, как описано выше для функции compareTo() .
fun main() < val lengthComparator = Comparator < str1: String, str2: String ->str1.length - str2.length > println(listOf("aaa", "bb", "c").sortedWith(lengthComparator)) // [c, bb, aaa] >
С помощью lengthComparator вы можете изменить порядок сортировки строк: вместо сортировки в лексикографическом порядке они будут отсортированы по длине.
Существует более упрощённый вариант использования Comparator — функция compareBy() из стандартной библиотеки. Она принимает лямбда-функцию, которая из объекта создаёт Comparable значение и задаёт пользовательский порядок, который по факту представляет собой естественный порядок созданных Comparable значений.
Используя compareBy() можно модифицировать lengthComparator из примера выше следующим образом:
Kotlin предоставляет функции, которые позволяют сортировать коллекции в естественном, пользовательском и даже в случайном порядке. В текущем разделе рассмотрены функции сортировки, которые работают только с неизменяемыми коллекциями. Такие функции возвращают результат сортировки в виде новой коллекции, содержащей элементы исходной коллекции, но упорядоченные в соответствии с заданным условием. Информация о функциях для сортировки изменяемых коллекций находится в разделе List: специфичные операции.
Естественный порядок
Основные функции sorted() и sortedDescending() возвращают элементы коллекции, отсортированные по возрастанию или убыванию в соответствии с их естественным порядком. Эти функции могут быть применены к коллекциям, содержащим элементы Comparable типа.
fun main() < val numbers = listOf("one", "two", "three", "four") println("Sorted ascending: $") // Sorted ascending: [four, one, three, two] println("Sorted descending: $") // Sorted descending: [two, three, one, four] >
Пользовательский порядок
Для сортировки объектов в пользовательском порядке или для сортировки объектов, не являющихся наследниками Comparable , существуют функции sortedBy() и sortedByDescending() . Они используют функцию-селектор для преобразования элементов коллекции в Comparable значения и сортируют коллекцию в естественном порядке этих значений.
fun main() < val numbers = listOf("one", "two", "three", "four") val sortedNumbers = numbers.sortedBy < it.length >println("Sorted by length ascending: $sortedNumbers") // Sorted by length ascending: [one, two, four, three] val sortedByLast = numbers.sortedByDescending < it.last() >println("Sorted by the last letter descending: $sortedByLast") // Sorted by the last letter descending: [four, two, one, three] >
Чтобы задать пользовательский порядок для сортировки коллекции, вы можете предоставить свой собственный Comparator . Для этого вызовите функцию sortedWith() и передайте ей свой Comparator . С помощью этой функции сортировка строк по их длине будет выглядеть следующим образом:
fun main() < val numbers = listOf("one", "two", "three", "four") println("Sorted by length ascending: $)>") // Sorted by length ascending: [one, two, four, three] >
Обратный порядок
С помощью функции reversed() вы можете получить коллекцию, отсортированную в обратном порядке.
reversed() возвращает новую коллекцию с копиями элементов из исходной коллекции. Поэтому, если вы измените исходную коллекцию, это не повлияет на ранее полученный от reversed() результат.
Другая функция — asReversed() — возвращает перевёрнутое представление исходной коллекции. Эта функция может быть более легковесной и предпочтительной, чем reversed() , при условии, что исходная коллекция не будет изменяться.
Если же в исходную коллекцию будут внесены изменения, все эти изменения отразятся в её перевёрнутых представлениях и наоборот.
Однако, если источник не является списком, либо неизвестно является ли список изменяемым, тогда функция reversed() более предпочтительна для использования, поскольку она возвращает копию, которая в будущем не изменится.
Случайный порядок
Наконец, существует функция shuffled() , которая возвращает новый List , содержащий элементы исходной коллекции в случайном порядке. Её можно вызывать либо без аргументов, либо с объектом Random .
sort
Sorts the array in-place according to the natural order of its elements.
The sort is stable. It means that equal elements preserve their order relative to each other after sorting.
import kotlin.test.* fun main(args: Array) < //sampleStart class Person(val firstName: String, val lastName: String) : Comparable < override fun compareTo(other: Person): Int = this.lastName.compareTo(other.lastName) override fun toString(): String = "$firstName $lastName" >val people = arrayOf( Person("Ragnar", "Lodbrok"), Person("Bjorn", "Ironside"), Person("Sweyn", "Forkbeard") ) // before sorting println(people.joinToString()) // Ragnar Lodbrok, Bjorn Ironside, Sweyn Forkbeard people.sort() // after sorting println(people.joinToString()) // Sweyn Forkbeard, Bjorn Ironside, Ragnar Lodbrok //sampleEnd >
Sorts a range in the array in-place.
The sort is stable. It means that equal elements preserve their order relative to each other after sorting.
import kotlin.test.* fun main(args: Array) < //sampleStart class Person(val firstName: String, val lastName: String) : Comparable < override fun compareTo(other: Person): Int = this.lastName.compareTo(other.lastName) override fun toString(): String = "$firstName $lastName" >val people = arrayOf( Person("Ragnar", "Lodbrok"), Person("Bjorn", "Ironside"), Person("Sweyn", "Forkbeard") ) // before sorting println(people.joinToString()) // Ragnar Lodbrok, Bjorn Ironside, Sweyn Forkbeard people.sort(0, 2) // after sorting println(people.joinToString()) // Bjorn Ironside, Ragnar Lodbrok, Sweyn Forkbeard //sampleEnd >
Parameters
fromIndex — the start of the range (inclusive) to sort, 0 by default.
toIndex — the end of the range (exclusive) to sort, size of this array by default.
Exceptions
IndexOutOfBoundsException — if fromIndex is less than zero or toIndex is greater than the size of this array.
IllegalArgumentException — if fromIndex is greater than toIndex.