How does asFlow() work for Iterable and Sequence, and when would you use it over flowOf?
answer
- asFlow = adapt existing producer to Flow
- Overloads: Iterable, Sequence, ranges, functions, arrays
- Roughly flow { forEach { emit } }
- Sequence one-shot consumed elsewhere can't replay
- flowOf = literals; asFlow = existing collection
basics
~20 sasFlow() is an extension that turns something you already have — a list, sequence, or range — into a Flow that emits each element. Use it when the values live in a collection; use flowOf for literal values you type out.
solid answer
~40 sasFlow() is a set of extension functions that adapt existing producers into a cold Flow. There are overloads for Iterable, Sequence, IntRange/LongRange, and even function types (() -> T and suspend () -> T). For Iterable and Sequence it iterates the source and emits each element in order. Like all cold flows, iteration restarts on every collect(), so an Iterable can be replayed but a single-pass Sequence iterator that's already consumed cannot. Choose asFlow() when values already exist in a collection or are generated by a function; choose flowOf(...) for a small fixed set of literal values. Functionally listOf(1,2,3).asFlow() and flowOf(1,2,3) behave the same, but asFlow expresses 'I have a collection' intent and avoids spreading large collections as varargs.
code
kotlin · 9 linesimport kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val list = listOf("x", "y", "z")
list.asFlow().collect { print(it) } // xyz
println()
(1..3).asFlow().collect { print(it) } // 123
}go deeper
Knows asFlow converts a list/range into a flow that emits each element.
Lists the overloads (Iterable, Sequence, ranges, functions) and explains intent vs flowOf.
Reasons about cold re-iteration, one-shot Sequence pitfalls, and the function overloads emitting one value.
Weighs API surface trade-offs (varargs vs collection adapters) and the laziness contract across overloads.
## What asFlow is `asFlow()` is a family of **extension functions** in `kotlinx.coroutines.flow` that convert an existing producer into a cold `Flow`. The common overloads: - `Iterable<T>.asFlow()` — e.g. on a `List`, `Set`. - `Sequence<T>.asFlow()`. - `IntRange.asFlow()`, `LongRange.asFlow()` (ranges are `Iterable`, but there are dedicated overloads). - `(() -> T).asFlow()` and `(suspend () -> T).asFlow()` — turn a function into a single-emission flow that calls the function on each collection. - `Array<T>.asFlow()` and primitive-array variants (e.g. `IntArray`). ```kotlin listOf(1, 2, 3).asFlow().collect { println(it) } // 1 2 3 (1..5).asFlow().collect { println(it) } // 1 2 3 4 5 sequenceOf("a", "b").asFlow().collect { println(it) } // a b ``` ## How it emits For `Iterable`/`Sequence`/range, it simply iterates the source and `emit`s each element in order, then completes. Internally it is roughly `flow { forEach { emit(it) } }`. ## Cold + re-iteration caveat Because flows are **cold**, the body re-runs on every `collect`. For an `Iterable` (like `List`) that means it is re-iterated each time — fine. But a `Sequence` backed by a one-shot iterator that has already been consumed elsewhere cannot be replayed; the safe case is a `Sequence` built from a repeatable generator such as `sequence { }` or `generateSequence`. ## Function overloads ```kotlin val f: suspend () -> Int = { computeValue() } f.asFlow().collect { println(it) } // calls computeValue() once per collection, emits result ``` This emits exactly one value: the function's return. ## asFlow vs flowOf - `flowOf(1, 2, 3)` — for a **fixed literal** set, passed as varargs. - `someList.asFlow()` — for values **already in a collection**, avoiding spreading large collections as varargs and expressing intent clearly. They are functionally interchangeable for the same elements but differ in ergonomics and intent.
- Is listOf(1,2,3).asFlow() different from flowOf(1,2,3) at runtime?Behaviorally they emit the same elements in order; the difference is ergonomic/intent — asFlow adapts an existing collection, flowOf takes varargs literals.
- What does ((): suspend () -> T).asFlow() emit?Exactly one value — the result of invoking the function — on each collection.
saying these in an interview costs you the question
- Claiming asFlow makes the flow hot
- Thinking asFlow caches values and won't re-iterate on a second collect
- Trying to asFlow an already-exhausted single-pass Sequence and expecting emissions
- Believing asFlow exists only for List