Kotlin Flow Operators
Flow operators sit between the builder and the collector and reshape the values on the way through. Each operator returns a new flow and the values keep their order.
map transforms each value
map multiplies each number by ten. collect prints the transformed values in the original order.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun numbers(): Flow<Int> = flow {
for (i in 1..4) emit(i)
}
fun main() = runBlocking {
numbers()
.map { it * 10 }
.collect { println("value $it") }
}filter keeps the matches
filter drops every odd number on the way through. Only the even values reach collect.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun numbers(): Flow<Int> = flow {
for (i in 1..6) emit(i)
}
fun main() = runBlocking {
numbers()
.filter { it % 2 == 0 }
.collect { println("even $it") }
}take stops after two values
The source emits five values, and take(2) ends the collection after the second one. The line after collect still runs.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun numbers(): Flow<Int> = flow {
for (i in 1..5) emit(i)
}
fun main() = runBlocking {
numbers()
.take(2)
.collect { println("value $it") }
println("collection stopped")
}A map and filter chain
Each number is squared first and the filter then keeps the squares above ten. The survivors print in source order.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun numbers(): Flow<Int> = flow {
for (i in 1..6) emit(i)
}
fun main() = runBlocking {
numbers()
.map { it * it }
.filter { it > 10 }
.collect { println("big square $it") }
}Example
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun scores(): Flow<Int> = flow {
for (i in 1..8) emit(i)
}
fun main() = runBlocking {
scores()
.filter { it % 2 == 1 }
.map { it * 3 }
.take(2)
.collect { println("score $it") }
println("done")
}Key points
- map turns each value into a new value before it moves on.
- filter keeps only the values that match its test.
- Operators chain, so each value passes through them in chain order.
- take(2) lets only the first two values reach the collector and then ends the collection.
- An operator chain is still cold and runs only at a terminal call.
- The transformed values arrive in the order the source emitted them.
In this example, the filter keeps the odd numbers one, three, five, and seven. map triples each one, and take(2) ends the collection after three and nine. The done line prints after collect returns.
Note
Placing an operator before or after another one changes which values it sees.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Kotlin Playground
Exercise
What does take(2) do in a flow chain?