map, filter и преобразования
Учимся преобразовывать и отбирать элементы коллекций без ручных циклов.
map создаёт новую коллекцию, применяя функцию к каждому элементу, а filter — отбирает элементы, удовлетворяющие условию.
Циклы для обработки коллекций часто многословны. Kotlin предлагает декларативный стиль: вы описываете, что нужно сделать с элементами, а не как их перебирать.
map — преобразование
map проходит по коллекции и возвращает новую, где каждый элемент заменён результатом лямбды.
fun main() {
val numbers = listOf(1, 2, 3, 4)
val squares = numbers.map { it * it }
println(squares)
val names = listOf("аня", "боря")
println(names.map { it.uppercase() })
}Вывод:
[1, 4, 9, 16] [АНЯ, БОРЯ]
filter — отбор
filter оставляет только элементы, для которых лямбда вернула true.
fun main() {
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evens = numbers.filter { it % 2 == 0 }
println(evens)
}Вывод:
[2, 4, 6]
Цепочки операций
Операции возвращают новую коллекцию, поэтому их удобно соединять в цепочку: отфильтровать, преобразовать, отсортировать, взять первые несколько.
fun main() {
val numbers = listOf(5, 3, 8, 1, 9, 2)
val result = numbers
.filter { it > 2 }
.map { it * 10 }
.sorted()
println(result)
}Вывод:
[30, 50, 80, 90]
Полезные операции
| Операция | Что делает |
sortedBy { ... } | сортировка по ключу |
take(n) | первые n элементов |
any { ... } | есть ли хоть один подходящий |
count { ... } | сколько элементов подходит |
Как работает под капотом
Каждая операция вроде map или filter создаёт новую коллекцию, не меняя исходную. В цепочке из нескольких операций промежуточные списки создаются на каждом шаге. Для коротких коллекций это незаметно, но для очень больших данных существуют Sequence — «ленивые» последовательности, обрабатывающие элементы по одному без промежуточных списков. Для учебных задач обычных операций над List вполне достаточно.
Частые ошибки
- Ждать, что
mapизменит исходный список. Он возвращает новую коллекцию; исходная не меняется. - Путать
mapиfilter.mapпреобразует каждый элемент,filterотбирает подходящие. - Писать вручную цикл там, где хватит одной операции.
list.filter { ... }короче и понятнее.
Итог
mapпреобразует каждый элемент,filterотбирает по условию.- Операции возвращают новую коллекцию и соединяются в цепочки.
- Исходная коллекция при этом не меняется.
- Для очень больших данных есть ленивые
Sequence.