In Kotlin, you can combine multiple collection operations by chaining functions like filter, map, sortedBy, take, groupBy, and others.
Each operation returns a new collection, so you can call the next operation directly on the result.
val numbers = listOf(1, 2, 3, 4, 5, 6)
val result = numbers
.filter { it % 2 == 0 }
.map { it * 10 }
.sorted()
println(result) // [20, 40, 60]
Here’s what happens:
filter { it % 2 == 0 }keeps only even numbersmap { it * 10 }transforms each numbersorted()sorts the result
You can also chain operations on objects:
data class User(
val name: String,
val age: Int,
val active: Boolean
)
val users = listOf(
User("Alice", 30, true),
User("Bob", 17, true),
User("Charlie", 25, false),
User("Diana", 22, true)
)
val activeAdultNames = users
.filter { it.active }
.filter { it.age >= 18 }
.map { it.name }
.sorted()
println(activeAdultNames) // [Alice, Diana]
You can often combine related filters into one:
val activeAdultNames = users
.filter { it.active && it.age >= 18 }
.map { it.name }
.sorted()
For maps, you can chain over entries:
val scores = mapOf(
"Alice" to 90,
"Bob" to 75,
"Charlie" to 85
)
val passedNames = scores
.filter { (_, score) -> score >= 80 }
.map { (name, _) -> name }
.sorted()
println(passedNames) // [Alice, Charlie]
If the collection is large or the chain is expensive, use asSequence() to make intermediate operations lazy:
val result = numbers
.asSequence()
.filter { it % 2 == 0 }
.map { it * 10 }
.sorted()
.toList()
Use regular collection chains for simple cases, and asSequence() when you want to avoid creating intermediate collections during multi-step processing.
