Functional Collection Operations
map, filter, reduce, and the other higher-order functions that replace hand-written loops for transforming collections.
3 min de lecture
Kotlin's collections come with a large set of built-in higher-order functions — the same idea introduced in the previous lesson's customFilter example, but written for you and heavily optimized. Learning a handful of these replaces the vast majority of manual loops you'd otherwise write.
map: transform every element
map produces a new collection by applying a lambda to each element:
val numbers = listOf(1, 2, 3, 4)
val doubled = numbers.map { it * 2 }
println(doubled) // [2, 4, 6, 8]
val names = listOf("alice", "bob")
val capitalized = names.map { it.replaceFirstChar(Char::uppercase) }
println(capitalized) // [Alice, Bob]filter: keep only what matches
filter produces a new collection containing only the elements where the lambda returns true:
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evens = numbers.filter { it % 2 == 0 }
println(evens) // [2, 4, 6]reduce and fold: combine into one value
reduce combines every element into a single result, using an accumulator that carries forward from one element to the next:
val numbers = listOf(1, 2, 3, 4)
val sum = numbers.reduce { acc, n -> acc + n }
println(sum) // 10fold does the same thing but takes an explicit starting value, which also makes it safe on an empty collection (reduce throws on an empty collection, since it has no first element to start from):
val total = numbers.fold(100) { acc, n -> acc + n }
println(total) // 110Chaining operations
These functions are designed to be chained, each one taking the previous result and transforming it further:
data class Product(val name: String, val price: Double, val inStock: Boolean)
val products = listOf(
Product("Keyboard", 49.99, true),
Product("Monitor", 199.99, false),
Product("Mouse", 19.99, true)
)
val totalInStockValue = products
.filter { it.inStock }
.map { it.price }
.sum()
println(totalInStockValue) // 69.98Read top to bottom, this says exactly what it does: keep only in-stock products, take their prices, add them up. A hand-written loop doing the same thing would need a mutable accumulator and an if check, mixing "what we're computing" with "how we're looping."
A few more worth knowing
val numbers = listOf(5, 3, 8, 1, 9)
println(numbers.sorted()) // [1, 3, 5, 8, 9]
println(numbers.first { it > 5 }) // 8 — first match
println(numbers.any { it > 8 }) // true — at least one matches
println(numbers.all { it > 0 }) // true — every element matches
println(numbers.count { it > 3 }) // 3Why this style is worth adopting
Each of these functions does exactly one thing, and chaining them reads like a description of the transformation rather than an implementation of it. That's not just nicer to read — it also means there's far less room for the off-by-one errors, forgotten accumulator resets, and mutable state bugs that hand-rolled loops tend to accumulate over time.
With collections covered, the next section moves into object-oriented Kotlin — starting with how classes and objects are declared.