Flow builder and collect in Kotlin - Time & Space Complexity
We want to understand how the time needed to run a Kotlin flow changes as we add more items to it.
How does the flow builder and collecting values scale with input size?
Analyze the time complexity of the following code snippet.
import kotlinx.coroutines.flow.*
fun simpleFlow(n: Int) = flow {
for (i in 1..n) {
emit(i)
}
}
suspend fun collectFlow(n: Int) {
simpleFlow(n).collect { value ->
println(value)
}
}
This code creates a flow that emits numbers from 1 to n, then collects and prints each number.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Loop inside the flow builder that emits n values.
- How many times: Exactly n times, once for each number from 1 to n.
- Collection operation: The collect block processes each emitted value once, also n times.
As n grows, the number of emitted and collected items grows linearly.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 emits and 10 collects |
| 100 | About 100 emits and 100 collects |
| 1000 | About 1000 emits and 1000 collects |
Pattern observation: The work grows directly in proportion to n, doubling n doubles the work.
Time Complexity: O(n)
This means the time to emit and collect all values grows linearly with the number of items.
[X] Wrong: "The flow emits all values instantly, so time does not depend on n."
[OK] Correct: Each value is emitted and collected one by one, so more items mean more work and more time.
Understanding how flows work with many items helps you reason about performance in real apps that use streams of data.
What if we changed the flow to emit values in parallel using multiple flows merged together? How would the time complexity change?
Practice
flow {} builder in Kotlin?Solution
Step 1: Understand the role of
Theflow {}flow {}builder creates a stream that can emit multiple values asynchronously over time.Step 2: Compare with other options
Options B, C, and D describe synchronous or non-stream behaviors, which do not matchflow {}usage.Final Answer:
To create a stream of values that can be emitted over time -> Option AQuick Check:
Flow builder = stream of values [OK]
- Confusing flow with suspend functions returning single values
- Thinking flow collects values instead of emitting them
- Assuming flow is synchronous
myFlow inside a suspend function?Solution
Step 1: Identify correct lambda syntax in Kotlin
Kotlin uses curly braces with parameter and arrow:{ param -> action }.Step 2: Match syntax with options
myFlow.collect { value -> println(value) } correctly uses{ value -> println(value) }. Options A lacks braces, B misses parameter declaration (value undefined), D uses wrong arrow symbol (=>).Final Answer:
myFlow.collect { value -> println(value) } -> Option CQuick Check:
Correct lambda syntax = myFlow.collect { value -> println(value) } [OK]
- Omitting lambda parameter name
- Using Java-style arrows (->) incorrectly
- Using parentheses instead of curly braces
import kotlinx.coroutines.flow.*
suspend fun main() {
val numbers = flow {
emit(1)
emit(2)
emit(3)
}
numbers.collect { println(it * 2) }
}Solution
Step 1: Analyze emitted values
The flow emits 1, 2, and 3 sequentially.Step 2: Understand the collect block
Each emitted value is multiplied by 2 and printed, so outputs are 2, 4, and 6.Final Answer:
2 4 6 -> Option BQuick Check:
Emitted values * 2 = 2,4,6 [OK]
- Printing original values without multiplication
- Expecting a list output instead of separate prints
- Assuming compilation error due to missing coroutine context
val flow = flow {
emit(1)
emit(2)
}
flow.collect { println(it) }Solution
Step 1: Check flow and collect usage
The flow builder and emit calls are correct.Step 2: Understand collect context
Collect is a suspend function and must be called from a suspend function or coroutine scope. Calling it directly without suspend context causes error.Final Answer:
Missing suspend modifier on the function calling collect -> Option DQuick Check:
collect requires suspend context [OK]
- Trying to call collect outside suspend or coroutine
- Confusing emit usage inside flow
- Thinking collect syntax is wrong
Solution
Step 1: Check flow emission of even numbers
val flow = flow { for (i in 1..5) { if (i % 2 == 0) emit(i) } } suspend fun main() { flow.collect { println(it) } } emits only even numbers inside the flow builder using a for loop and condition.Step 2: Verify collection and printing
val flow = flow { for (i in 1..5) { if (i % 2 == 0) emit(i) } } suspend fun main() { flow.collect { println(it) } } collects the flow inside a suspend function and prints each emitted value correctly.Final Answer:
val flow = flow { for (i in 1..5) { if (i % 2 == 0) emit(i) } } suspend fun main() { flow.collect { println(it) } } -> Option AQuick Check:
Emit filtered values inside flow, collect in suspend [OK]
- Calling collect outside suspend function
- Filtering after emitting all values instead of inside flow
- Not using suspend function for collect
Ready to prove it?
Pass the test and this pattern moves unknown
