Spec-Zone.ru › Kotlin 1.8

Порядок элементов

Порядок элементов является важным аспектом некоторых типов коллекций. Например, два списка с одними и теми же элементами не равны, если их элементы упорядочены по-разному.

В Kotlin порядок объектов может быть определён несколькими способами.

Во-первых, существует естественный порядок. Он определён для реализаций интерфейса Comparable. Естественный порядок используется для сортировки элементов, когда не указан другой порядок.

Большинство встроенных типов являются сравнимыми:

  • Числовые типы используют традиционный числовой порядок: 1 больше, чем 0; -3.4f больше, чем -5f, и так далее.

  • Char и String используют лексикографический порядок: b больше, чем a; world больше, чем hello.

Чтобы определить естественный порядок для пользовательского типа, сделайте тип реализацией интерфейса Comparable. Это требует реализации функции compareTo(). Функция compareTo() должна принимать другой объект того же типа в качестве аргумента и возвращать целочисленное значение, показывающее, какой объект больше:

  • Положительные значения показывают, что объект-получатель больше.

  • Отрицательные значения показывают, что он меньше аргумента.

  • Ноль показывает, что объекты равны.

Ниже представлен класс для упорядочивания версий, состоящих из основной и дополнительной части.

class Version(val major: Int, val minor: Int): Comparable<Version> {
    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))
}

Пользовательский порядок позволяет сортировать экземпляры любого типа так, как вам нужно. В частности, вы можете определить порядок для несопоставимых объектов или определить порядок, отличный от естественного, для сравнимого типа. Чтобы определить пользовательский порядок для типа, создайте для него Comparator. Comparator содержит функцию compare(): она принимает два экземпляра класса и возвращает целочисленный результат сравнения между ними. Результат интерпретируется так же, как результат compareTo(), как описано выше.

fun main() {
//sampleStart
    val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
    println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
//sampleEnd
}

Имея lengthComparator, вы можете упорядочить строки по их длине вместо лексикографического порядка по умолчанию.

Более короткий способ определения Comparator — функция compareBy() из стандартной библиотеки. Функция compareBy() принимает лямбда-функцию, которая создает значение Comparable из экземпляра, и определяет пользовательский порядок как естественный порядок созданных значений.

С помощью compareBy(), компаратор длины из примера выглядит следующим образом:

fun main() {
//sampleStart    
    println(listOf("aaa", "bb", "c").sortedWith(compareBy { it.length }))
//sampleEnd
}

Пакет Kotlin collections предоставляет функции для сортировки коллекций в естественном, пользовательском и даже случайном порядке. На этой странице мы опишем функции сортировки, которые применяются к только для чтения коллекциям. Эти функции возвращают свой результат в виде новой коллекции, содержащей элементы исходной коллекции в нужном порядке. Чтобы узнать о функциях для сортировки изменяемых коллекций на месте, см. операции, специфичные для списков.

Естественный порядок

Базовые функции sorted() и sortedDescending() возвращают элементы коллекции, отсортированные в возрастающем и убывающем порядке соответственно в соответствии с их естественным порядком. Эти функции применяются к коллекциям элементов Comparable.

fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")

    println("Sorted ascending: ${numbers.sorted()}")
    println("Sorted descending: ${numbers.sortedDescending()}")
//sampleEnd
}

Пользовательские порядки

Для сортировки в пользовательских порядках или для сортировки несравнимых объектов существуют функции sortedBy() и sortedByDescending(). Они принимают функцию-селектор, которая отображает элементы коллекции в значения Comparable и сортирует коллекцию в естественном порядке этих значений.

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
}

Чтобы определить пользовательский порядок для сортировки коллекции, вы можете предоставить собственный Comparator. Для этого вызовите функцию sortedWith(), передав в неё свой Comparator. С помощью этой функции сортировка строк по их длине выглядит так:

fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")
    println("Sorted by length ascending: ${numbers.sortedWith(compareBy { it.length })}")
//sampleEnd
}

Обратный порядок

Вы можете получить коллекцию в обратном порядке, используя функцию reversed().

fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")
    println(numbers.reversed())
//sampleEnd
}

reversed() возвращает новую коллекцию с копиями элементов. Таким образом, если вы измените исходную коллекцию позже, это не повлияет на ранее полученные результаты reversed().

Другая функция обратного порядка - asReversed()

  • возвращает вид обратной коллекции того же экземпляра коллекции, поэтому он может быть более лёгким и предпочтительным по сравнению с reversed() если исходный список не будет меняться.

fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")
    val reversedNumbers = numbers.asReversed()
    println(reversedNumbers)
//sampleEnd
}

Если исходный список изменяемый, все его изменения отражаются в его обратных представлениях и наоборот.

fun main() {
//sampleStart
    val numbers = mutableListOf("one", "two", "three", "four")
    val reversedNumbers = numbers.asReversed()
    println(reversedNumbers)
    numbers.add("five")
    println(reversedNumbers)
//sampleEnd
}

Однако, если изменчивость списка неизвестна или источник не является списком вообще, reversed() предпочтительнее, поскольку его результат является копией, которая не изменится в будущем.

Случайный порядок

Наконец, есть функция, которая возвращает новую List, содержащую элементы коллекции в случайном порядке - shuffled(). Вы можете вызвать её без аргументов или с объектом Random.

fun main() {
//sampleStart
     val numbers = listOf("one", "two", "three", "four")
     println(numbers.shuffled())
//sampleEnd
}
Последнее изменение: 10 января 2023
Получение отдельных элементов Агрегатные операции

© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/collection-ordering.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API