🎓 A1Learner
🔍
0 of 28 lessons completed

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?