Операции, специфичные для списков
List — самый популярный тип встроенной коллекции в Kotlin. Доступ к элементам списков по индексу предоставляет широкий набор операций со списками.
Получение элементов по индексу
Для списков доступны все распространённые операции получения элементов: elementAt(), first(), last() и другие, перечисленные в разделе Получение отдельных элементов. Особенность списков — доступ к элементам по индексу, поэтому самый простой способ прочитать элемент — получить его по индексу. Для этого используется функция get(), которой передаётся индекс в качестве аргумента, либо сокращённый синтаксис [index].
Если размер списка меньше указанного индекса, возникает исключение. Чтобы избежать таких исключений, можно воспользоваться двумя другими функциями:
getOrElse()позволяет указать функцию для вычисления значения по умолчанию, возвращаемого, если указанный индекс отсутствует в коллекции.getOrNull()возвращаетnullв качестве значения по умолчанию.
fun main() {
//sampleStart
val numbers = listOf(1, 2, 3, 4)
println(numbers.get(0))
println(numbers[0])
//numbers.get(5) // exception!
println(numbers.getOrNull(5)) // null
println(numbers.getOrElse(5, {it})) // 5
//sampleEnd
}
Получение частей списка
Помимо общих операций для получения частей коллекции, в списках доступна функция subList(), которая возвращает представление указанного диапазона элементов в виде списка. Поэтому при изменении элемента исходной коллекции он также изменяется в ранее созданных подсписках, и наоборот.
fun main() {
//sampleStart
val numbers = (0..13).toList()
println(numbers.subList(3, 6))
//sampleEnd
}
Поиск позиций элементов
Линейный поиск
В любом списке можно найти позицию элемента с помощью функций indexOf() и lastIndexOf(). Они возвращают первую и последнюю позиции элемента, равного переданному аргументу, в списке. Если таких элементов нет, обе функции возвращают -1.
fun main() {
//sampleStart
val numbers = listOf(1, 2, 3, 4, 2, 5)
println(numbers.indexOf(2))
println(numbers.lastIndexOf(2))
//sampleEnd
}
Также есть пара функций, которые принимают предикат и ищут соответствующие ему элементы:
indexOfFirst()возвращает индекс первого элемента, соответствующего предикату, или-1, если таких элементов нет.indexOfLast()возвращает индекс последнего элемента, соответствующего предикату, или-1, если таких элементов нет.
fun main() {
//sampleStart
val numbers = mutableListOf(1, 2, 3, 4)
println(numbers.indexOfFirst { it > 2})
println(numbers.indexOfLast { it % 2 == 1})
//sampleEnd
}
Двоичный поиск в отсортированных списках
Есть ещё один способ поиска элементов в списках — двоичный поиск. Он работает значительно быстрее других встроенных функций поиска, но требует, чтобы список был отсортирован по возрастанию в соответствии с некоторым порядком: естественным или заданным в параметре функции. В противном случае результат не определён.
Чтобы найти элемент в отсортированном списке, вызовите функцию binarySearch(), передав значение в качестве аргумента. Если такой элемент существует, функция возвращает его индекс; в противном случае она возвращает (-insertionPoint - 1), где insertionPoint — индекс, по которому следует вставить этот элемент, чтобы список остался отсортированным. Если элементов с указанным значением несколько, поиск может вернуть индекс любого из них.
Можно также указать диапазон индексов для поиска: в этом случае функция ищет только между двумя заданными индексами.
fun main() {
//sampleStart
val numbers = mutableListOf("one", "two", "three", "four")
numbers.sort()
println(numbers)
println(numbers.binarySearch("two")) // 3
println(numbers.binarySearch("z")) // -5
println(numbers.binarySearch("two", 0, 2)) // -3
//sampleEnd
}
Двоичный поиск с компаратором
Если элементы списка не являются Comparable, для двоичного поиска следует указать Comparator. Список должен быть отсортирован по возрастанию в соответствии с этим Comparator. Рассмотрим пример:
data class Product(val name: String, val price: Double)
fun main() {
//sampleStart
val productList = listOf(
Product("WebStorm", 49.0),
Product("AppCode", 99.0),
Product("DotTrace", 129.0),
Product("ReSharper", 149.0))
println(productList.binarySearch(Product("AppCode", 99.0), compareBy<Product> { it.price }.thenBy { it.name }))
//sampleEnd
}
Здесь приведён список экземпляров Product, которые не являются Comparable, и Comparator, задающий порядок: товар p1 предшествует товару p2, если цена p1 меньше цены p2. Имея список, отсортированный по возрастанию в соответствии с этим порядком, мы используем binarySearch(), чтобы найти индекс указанного Product.
Пользовательские компараторы также полезны, когда список упорядочен не естественным образом, например без учёта регистра для элементов типа String.
fun main() {
//sampleStart
val colors = listOf("Blue", "green", "ORANGE", "Red", "yellow")
println(colors.binarySearch("RED", String.CASE_INSENSITIVE_ORDER)) // 3
//sampleEnd
}
Двоичный поиск с функцией сравнения
Двоичный поиск с функцией сравнения позволяет находить элементы без указания конкретных искомых значений. Вместо этого он принимает функцию сравнения, сопоставляющую элементы со значениями Int, и ищет элемент, для которого функция возвращает ноль. Список должен быть отсортирован по возрастанию в соответствии с переданной функцией; другими словами, возвращаемые функцией сравнения значения должны возрастать от одного элемента списка к следующему.
import kotlin.math.sign
//sampleStart
data class Product(val name: String, val price: Double)
fun priceComparison(product: Product, price: Double) = sign(product.price - price).toInt()
fun main() {
val productList = listOf(
Product("WebStorm", 49.0),
Product("AppCode", 99.0),
Product("DotTrace", 129.0),
Product("ReSharper", 149.0))
println(productList.binarySearch { priceComparison(it, 99.0) })
}
//sampleEnd
Двоичный поиск с компаратором и с функцией сравнения также можно выполнять в диапазонах списка.
Операции записи для списков
Помимо операций изменения коллекций, описанных в разделе Операции записи для коллекций, изменяемые списки поддерживают специальные операции записи. Такие операции используют индекс для доступа к элементам и расширяют возможности изменения списков.
Добавление
Чтобы добавить элементы в определённую позицию списка, используйте add() и addAll(), передав позицию вставки элемента в качестве дополнительного аргумента. Все элементы, расположенные после этой позиции, сдвигаются вправо.
fun main() {
//sampleStart
val numbers = mutableListOf("one", "five", "six")
numbers.add(1, "two")
numbers.addAll(2, listOf("three", "four"))
println(numbers)
//sampleEnd
}
Обновление
В списках также есть функция для замены элемента в заданной позиции — set() и её операторная форма []. set() не изменяет индексы других элементов.
fun main() {
//sampleStart
val numbers = mutableListOf("one", "five", "three")
numbers[1] = "two"
println(numbers)
//sampleEnd
}
fill() просто заменяет все элементы коллекции указанным значением.
fun main() {
//sampleStart
val numbers = mutableListOf(1, 2, 3, 4)
numbers.fill(3)
println(numbers)
//sampleEnd
}
Удаление
Чтобы удалить элемент из определённой позиции списка, используйте функцию removeAt(), передав позицию в качестве аргумента. Все индексы элементов, расположенных после удаляемого элемента, уменьшатся на единицу.
fun main() {
//sampleStart
val numbers = mutableListOf(1, 2, 3, 4, 3)
numbers.removeAt(1)
println(numbers)
//sampleEnd
}
Сортировка
В разделе Упорядочивание коллекций описаны операции, позволяющие получать элементы коллекции в заданном порядке. Для изменяемых списков стандартная библиотека предоставляет похожие функции расширения, которые выполняют те же операции упорядочивания на месте. При применении такой операции к экземпляру списка порядок элементов изменяется именно в этом экземпляре.
Функции сортировки на месте имеют названия, похожие на названия функций для списков только для чтения, но без суффикса ed/d:
В названиях всех функций сортировки используется
sort*вместоsorted*:sort(),sortDescending(),sortBy()и так далее.shuffle()вместоshuffled().reverse()вместоreversed().
Вызов asReversed() для изменяемого списка возвращает другой изменяемый список, представляющий собой перевёрнутое представление исходного списка. Изменения в этом представлении отражаются в исходном списке. В следующем примере показаны функции сортировки для изменяемых списков:
fun main() {
//sampleStart
val numbers = mutableListOf("one", "two", "three", "four")
numbers.sort()
println("Sort into ascending: $numbers")
numbers.sortDescending()
println("Sort into descending: $numbers")
numbers.sortBy { it.length }
println("Sort into ascending by length: $numbers")
numbers.sortByDescending { it.last() }
println("Sort into descending by the last letter: $numbers")
numbers.sortWith(compareBy<String> { it.length }.thenBy { it })
println("Sort by Comparator: $numbers")
numbers.shuffle()
println("Shuffle: $numbers")
numbers.reverse()
println("Reverse: $numbers")
//sampleEnd
}
© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/list-operations.html