Освой Kotlin играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Коллекции

Коллекции в Kotlin используют множество различных интерфейсов: Iterable, Collection, Set, List, MutableIterable, MutableCollection и др.

В Kotlin нет собственных коллекций, только Java-коллекции. Но при этом в Kotlin они обладают более широкими возможностями, используя расширения. Например, вы можете узнать последний элемент списка или найти максимальное значение в коллекции чисел.

Важная особенность - в Kotlin интерфейсы явно разделены на две группы - изменяемые и неизменяемые. Старайтесь всегда использовать неизменяемые коллекции с доступом для чтения. Если вам нужно изменять коллекцию, то тогда выбирайте другой вариант. Здесь не надо путать с var и val. Если вы создадите список для чтения и привяжете его к переменной var, список всё равно нельзя будет изменить после создания.

Для создания различных типов коллекций есть разные функции.

Функции associate(), associateTo(), associateBy()

Функция associate() позволяет получить Map, используя поля класса как ключ и значение. Например, в нашем случае имена станут ключами, а возраст - ассоциированными значениями.


val cats = listOf(
    Cat("Barsik", 5, 1),
    Cat("Murzik", 9, 2)
)

val associatedMap = cats.associate { Pair(it.name, it.age) }
println(associatedMap)

// Результат
{Barsik=5, Murzik=9}

Функция associateTo() - Зададим отображение originalMap, где ключ является строкой, а значением число. Берём список и применяем наше отображение, указывая нужные поля класса (имя и вес).


val originalMap = mutableMapOf<String, Int>()
cats.associateTo(originalMap) { it.name to it.weight }
println(originalMap)

// Результат
{Barsik=1, Murzik=2}

Функция flatMap()

Функция flatMap() работает с коллекцией, содержащей коллекции, и возвращает объединённую «плоскую» коллекцию, содержащую все элементы исходных коллекций.


val result = listOf(listOf(1, 2, 3), listOf(4, 5, 6)).flatMap { it }
println(result) // [1, 2, 3, 4, 5, 6]

Функция map()

Функция map() проходит по каждому элементу и делает операции с элементом в лямбде-выражении, объединяя результаты в новую коллекцию.

map()

Умножаем каждый элемент списка на себя.


var list = listOf(1, 2, 3)
var dest = list.map { it * it }
println(dest.toString()) // выводит [1, 4, 9]

Выводим только имена, игнорируя возраст и другие поля класса.


val cats = listOf(Cat("Barsik", 5, true),
        Cat("Murzik", 9, true))
println(cats.map (Cat::name))
// или println(cats.map {it.name})

Можно объединить вызовы функций в цепочки. Выводим имена котов, чей возраст больше 5.


val cats = listOf(Cat("Barsik", 5, true),
        Cat("Murzik", 9, true))
println(cats.filter {it.age > 5}.map (Cat::name))

Удаляем префикс у строк списка.


val cats = listOf("!Мурзик", "!Рыжик", "Барсик")
val shortCats = cats.map { name ->
    name.removePrefix("!")
}
println(shortCats)

Функция mapIndexed()

Если при переборе нужна информация об индексах, то используйте mapIndexed().

mapIndexed()


var list = listOf(8, 4, 2)
var dest = list.mapIndexed { index, i ->  "$index: $i"}
println(dest.toString()) // выводит [0: 8, 1: 4, 2: 2]

Функция mapNotNull()

Если нужно вернуть коллекцию без элементов null, то используйте mapNotNull().


val list = listOf("Барсик", null, "Васька", null, "Мурзик")
val dest = list.mapNotNull { it?.length }
println(dest.toString()) // выводит [6, 6, 6]

val set = setOf("Барсик", null, "Васька", null, "Мурзик")
val newSet = set.mapNotNull { it?.last() }
println(newSet.toString()) // выводит [к, а, к]

Также есть функция mapIndexedNotNull().

Операции с двумя коллекциями

Функция zip()

Функция-комбинатор zip() принимает разные коллекции и объединяют их в одну новую.

zip()

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


val names = listOf("Барсик", "Мурзик", "Рыжик")
val sizes = listOf("большой", "средний", "совсем котёнок")
val catMap = names.zip(sizes).toMap()
// обращаемся к ключу
println(catMap["Рыжик"]) // совсем котёнок

unzip()

Функция unzip() является полной противоположностью функции zip(). Если у нас есть список пар, то функция разобьёт пары на два списка - в первом будут первые элементы пары, во втором будут вторые элементы каждой пары.

unzip()


val pairs = listOf(Pair("Россия", "рубль"), Pair("США", "доллар"), Pair("Украина", "гривна"))
println(pairs.unzip().toString()) // выводит ([Россия, США, Украина], [рубль, доллар, гривна])
Реклама