Spec-Zone.ru › Kotlin 2

Операции преобразования коллекций

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

Отображение

Преобразование с отображением создает коллекцию из результатов применения функции к элементам другой коллекции. Основная функция отображения — map(). Она применяет заданную лямбда-функцию к каждому элементу по очереди и возвращает список результатов этой лямбда-функции. Порядок результатов совпадает с исходным порядком элементов. Чтобы применить преобразование, которое дополнительно использует индекс элемента в качестве аргумента, используйте mapIndexed().


fun main() {
//sampleStart
    val numbers = setOf(1, 2, 3)
    println(numbers.map { it * 3 })
    println(numbers.mapIndexed { idx, value -> value * idx })
//sampleEnd
}

Если при преобразовании для некоторых элементов получается null, отфильтровать null из результирующей коллекции можно, вызвав функцию mapNotNull() вместо map() или mapIndexedNotNull() вместо mapIndexed().


fun main() {
//sampleStart
    val numbers = setOf(1, 2, 3)
    println(numbers.mapNotNull { if ( it == 2) null else it * 3 })
    println(numbers.mapIndexedNotNull { idx, value -> if (idx == 0) null else value * idx })
//sampleEnd
}

При преобразовании отображений есть два варианта: преобразовать ключи, оставив значения без изменений, или наоборот. Чтобы применить заданное преобразование к ключам, используйте mapKeys(); функция mapValues(), в свою очередь, преобразует значения. Обе функции используют преобразования, принимающие в качестве аргумента запись отображения, поэтому с их помощью можно работать и с ключом, и со значением.


fun main() {
//sampleStart
    val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
    println(numbersMap.mapKeys { it.key.uppercase() })
    println(numbersMap.mapValues { it.value + it.key.length })
//sampleEnd
}

Объединение

Объединение в пары — это преобразование, при котором из элементов, занимающих одинаковые позиции в двух коллекциях, создаются пары. В стандартной библиотеке Kotlin для этого используется функция-расширение zip().

При вызове для коллекции или массива с другой коллекцией (или массивом) в качестве аргумента функция zip() возвращает List объектов Pair. Элементы исходной коллекции становятся первыми элементами этих пар.

Если размеры коллекций различаются, размер результата zip() будет равен размеру меньшей коллекции; последние элементы большей коллекции не войдут в результат.

Функцию zip() также можно вызвать в инфиксной форме a zip b.


fun main() {
//sampleStart
    val colors = listOf("red", "brown", "grey")
    val animals = listOf("fox", "bear", "wolf")
    println(colors zip animals)

    val twoAnimals = listOf("fox", "bear")
    println(colors.zip(twoAnimals))
//sampleEnd
}

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


fun main() {
//sampleStart
    val colors = listOf("red", "brown", "grey")
    val animals = listOf("fox", "bear", "wolf")
    
    println(colors.zip(animals) { color, animal -> "The ${animal.replaceFirstChar { it.uppercase() }} is $color"})
//sampleEnd
}

Если у вас есть List из Pair, можно выполнить обратное преобразование — разделение пар, которое создает из этих пар два списка:

  • Первый список содержит первые элементы каждой Pair из исходного списка.

  • Второй список содержит вторые элементы.

Чтобы разделить список пар, вызовите unzip().


fun main() {
//sampleStart
    val numberPairs = listOf("one" to 1, "two" to 2, "three" to 3, "four" to 4)
    println(numberPairs.unzip())
//sampleEnd
}

Ассоциирование

Преобразования ассоциирования позволяют создавать отображения из элементов коллекции и связанных с ними значений. В зависимости от типа ассоциирования элементы могут становиться ключами или значениями в отображении.

Основная функция ассоциирования associateWith() создает Map, в котором элементы исходной коллекции являются ключами, а значения формируются из них с помощью заданной функции преобразования. Если два элемента равны, в отображении остается только последний из них.


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

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

Функцию associateBy() также можно вызвать с функцией преобразования значений.


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

    println(numbers.associateBy { it.first().uppercaseChar() })
    println(numbers.associateBy(keySelector = { it.first().uppercaseChar() }, valueTransform = { it.length }))
//sampleEnd
}

Еще один способ создавать отображения, в которых и ключи, и значения формируются из элементов коллекции, — использовать функцию associate(). Она принимает лямбда-функцию, возвращающую Pair: ключ и значение соответствующей записи отображения.

Обратите внимание: associate() создает недолговечные объекты Pair, что может повлиять на производительность. Поэтому associate() следует использовать, когда производительность не критична или этот вариант предпочтительнее других.

Пример такого случая — когда ключ и соответствующее ему значение создаются одновременно из одного элемента.


fun main() {
data class FullName (val firstName: String, val lastName: String)

fun parseFullName(fullName: String): FullName {
    val nameParts = fullName.split(" ")
    if (nameParts.size == 2) {
        return FullName(nameParts[0], nameParts[1])
    } else throw Exception("Wrong name format")
}

//sampleStart
    val names = listOf("Alice Adams", "Brian Brown", "Clara Campbell")
    println(names.associate { name -> parseFullName(name).let { it.lastName to it.firstName } })  
//sampleEnd
}

Здесь мы сначала вызываем функцию преобразования для элемента, а затем создаем пару из свойств результата этой функции.

Сведение

Если вы работаете с вложенными коллекциями, вам могут пригодиться функции стандартной библиотеки, обеспечивающие прямой доступ к элементам вложенных коллекций.

Первая такая функция — flatten(). Ее можно вызвать для коллекции коллекций, например для List из Set. Функция возвращает единый List, содержащий все элементы вложенных коллекций.


fun main() {
//sampleStart
    val numberSets = listOf(setOf(1, 2, 3), setOf(4, 5, 6), setOf(1, 2))
    println(numberSets.flatten())
//sampleEnd
}

Другая функция — flatMap() — позволяет гибко обрабатывать вложенные коллекции. Она принимает функцию, преобразующую элемент коллекции в другую коллекцию. В результате flatMap() возвращает единый список значений, полученных при применении этой функции ко всем элементам. Таким образом, flatMap() работает как последовательный вызов map() (с коллекцией в качестве результата отображения) и flatten().


data class StringContainer(val values: List<String>)

fun main() {
//sampleStart
    val containers = listOf(
        StringContainer(listOf("one", "two", "three")),
        StringContainer(listOf("four", "five", "six")),
        StringContainer(listOf("seven", "eight"))
    )
    println(containers.flatMap { it.values })
//sampleEnd
}

Строковое представление

Если нужно получить содержимое коллекции в удобочитаемом формате, используйте функции преобразования коллекций в строки: joinToString() и joinTo().

joinToString() создает одну String из элементов коллекции на основе переданных аргументов. joinTo() делает то же самое, но добавляет результат в заданный объект Appendable.

При вызове с параметрами по умолчанию эти функции возвращают результат, аналогичный вызову toString() для коллекции: String строковых представлений элементов, разделенных запятыми и пробелами.


fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")
    
    println(numbers)         
    println(numbers.joinToString())
    
    val listString = StringBuffer("The list of numbers: ")
    numbers.joinTo(listString)
    println(listString)
//sampleEnd
}

Чтобы создать строковое представление в заданном формате, можно указать значения аргументов функции separator, prefix и postfix. Полученная строка будет начинаться с prefix и заканчиваться на postfix. После каждого элемента, кроме последнего, будет добавлено separator.


fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")    
    println(numbers.joinToString(separator = " | ", prefix = "start: ", postfix = ": end"))
//sampleEnd
}

Для больших коллекций можно задать limit — количество элементов, включаемых в результат. Если размер коллекции превышает limit, все остальные элементы будут заменены одним значением аргумента truncated.


fun main() {
//sampleStart
    val numbers = (1..100).toList()
    println(numbers.joinToString(limit = 10, truncated = "<...>"))
//sampleEnd
}

Наконец, чтобы настроить представление самих элементов, задайте функцию transform.


fun main() {
//sampleStart
    val numbers = listOf("one", "two", "three", "four")
    println(numbers.joinToString { "Element: ${it.uppercase()}"})
//sampleEnd
}
4 июля 2025 г.
ГруппировкаФильтрация коллекций

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

Spec-Zone.ru

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