combine and zip: Merging Multiple Flows
Combine multiple Flows and zip their emissions together.
combine and zip: Merging Multiple Flows is a free Kotlin Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, and your progress syncs across the web and the CoddyKit app. The Kotlin Academy course includes 4 lessons in total.
Why Merge Flows?
Real apps often need to combine multiple data streams: user preferences + network data, form fields + validation state. Kotlin Flow provides zip, combine, and merge for this.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val names = flowOf("Alice", "Bob", "Carol")
val ages = flowOf(30, 25, 35)
names.zip(ages) { name, age -> "$name is $age" }
.collect { println(it) }
}zip: Paired Emissions
zip pairs emissions one-to-one in order. It stops when the shorter flow ends.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val a = flowOf(1, 2, 3, 4) // 4 elements
val b = flowOf("a", "b", "c") // 3 elements — zip stops here
a.zip(b) { n, s -> "$n-$s" }
.collect { println(it) } // 1-a, 2-b, 3-c
}combine: Latest Values
combine emits a new value whenever any of the flows emits, using the latest value from each. Both flows must have emitted at least once.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val flow1 = MutableStateFlow(1)
val flow2 = MutableStateFlow("a")
combine(flow1, flow2) { n, s -> "$n-$s" }
.take(1)
.collect { println(it) } // 1-a
}combine vs zip Difference
zip: waits for matching pair. combine: fires on every update using latest values. Use combine for reactive UI (e.g., two form fields), zip for sequential pairing.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
// zip: 1-a, 2-b
val nums = flowOf(1, 2).zip(flowOf("a", "b")) { n, s -> "$n-$s" }
nums.collect { println("zip: $it") }
// combine fires more:
combine(flowOf(1, 2), flowOf("a")) { n, s -> "$n-$s" }
.collect { println("combine: $it") }
}merge: Interleaving Flows
merge emits from multiple flows as they arrive, without pairing — output order depends on emission timing.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val a = flow { emit("A1"); delay(50); emit("A2") }
val b = flow { delay(25); emit("B1") }
merge(a, b).collect { println(it) } // A1, B1, A2
}combine with 3+ Flows
combine supports multiple flows. Pass them as vararg and the lambda receives all latest values.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val a = MutableStateFlow("hello")
val b = MutableStateFlow(42)
val c = MutableStateFlow(true)
combine(a, b, c) { s, n, flag -> "$s-$n-$flag" }
.take(1)
.collect { println(it) } // hello-42-true
}flatMapMerge: Concurrent Inner Flows
flatMapMerge maps each element to a flow and collects all inner flows concurrently, merging their outputs.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
(1..3).asFlow()
.flatMapMerge { n ->
flow { delay(100L - n * 10); emit("result-$n") }
}
.collect { println(it) }
}flatMapLatest: Cancel on New Emission
flatMapLatest cancels the current inner flow when a new element arrives upstream — perfect for search-as-you-type.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flowOf("k", "ko", "kot", "kotl", "kotli", "kotlin")
.flatMapLatest { query ->
flow {
delay(50) // simulate debounced search
emit("Result for: $query")
}
}
.collect { println(it) } // only "Result for: kotlin"
}zip for Transaction Pairing
Use zip to pair events from two streams: e.g., user actions with server confirmations, ensuring 1-to-1 correspondence.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val orders = flowOf("Order1", "Order2", "Order3")
val confirmations = flowOf("Confirmed", "Confirmed", "Rejected")
orders.zip(confirmations) { order, status -> "$order: $status" }
.collect { println(it) }
}combine for Form Validation
Combine username and password flows to reactively compute form validity — updates whenever either field changes.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
val username = MutableStateFlow("")
val password = MutableStateFlow("")
val isValid = combine(username, password) { u, p ->
u.length >= 3 && p.length >= 8
}
username.value = "alice"
password.value = "secure123"
println(isValid.first()) // true
}onEach + combine for Multi-Source Loading
Combine a loading flag with a data flow to produce a single UI state object from multiple independent sources.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
data class UI(val loading: Boolean, val data: String)
fun main() = runBlocking {
val loading = MutableStateFlow(true)
val data = MutableStateFlow("")
combine(loading, data) { l, d -> UI(l, d) }
.take(2)
.collect { println(it) }
data.value = "result"
loading.value = false
}Quick Check
What is the key difference between zip and combine?
Recap
zip pairs emissions sequentially; combine fires on any update using latest values; merge interleaves independent flows; flatMapLatest cancels stale inner flows. Choose based on pairing vs. reactivity needs.
Learn Kotlin with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 51
- Lessons
- 203
Frequently Asked Questions
Is the “combine and zip: Merging Multiple Flows” lesson free?
Yes — any 3 lessons of the Kotlin Academy learning path, including “combine and zip: Merging Multiple Flows”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Kotlin Academy course includes 4 lessons in total.
What will I learn in “combine and zip: Merging Multiple Flows”?
Combine multiple Flows and zip their emissions together. You practise Kotlin Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Kotlin Academy?
No prior experience is required. Kotlin Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.
How long does the “combine and zip: Merging Multiple Flows” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Kotlin Academy lesson?
Yes. Every Kotlin Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Flow Operators: map, filter, transform, and take
- catch and onCompletion: Error Handling in Flow
- combine and zip: Merging Multiple Flows
- flowOn and buffer: Context and Backpressure