# Chapter 19 : UseCase16 - combine (Reactive  Composition)

In this chapter we learn how to combine multiple independent streams into one reactive result.

### What We Are Learning

We are learning how to react when **any** of multiple flows changes.

**combine** is used when:

*   Two data sources influence one output
    
*   Filters + data must react together
    
*   User input + database result must update UI
    
*   Multiple signals produce derived state
    

### Our Stock Scenario

Assumptions:

We have:

1.  A flow of stocks
    
2.  A flow of minimum price filter
    

Whenever:

*   Stock list changes  
    OR
    
*   Filter changes
    

We want to recompute the filtered stock list. That is the utility of **combine**.

### How combine Works

### combine(A, B)

*   Waits until both flows emit at least once
    
*   Then emits a new value every time either flow emits
    
*   Always uses the latest value from both flows
    

It does **not** wait for them to move together.

```kotlin
package org.kotlinflowlearner.stockflow.usecases.uc16

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flow
import org.kotlinflowlearner.stockflow.model.Stock

/**
 * UC16 demonstrates the combine operator.
 *
 * This use case combines two independent flows:
 * 1. A flow emitting stock list updates
 * 2. A flow emitting minimum price filter updates
 *
 * Whenever either flow emits, a new filtered list is produced.
 */
class UC16Combine {

    /**
     * Executes the use case.
     *
     * @param stocks The in-memory list of stocks loaded from CSV.
     * @return A Flow emitting filtered stock lists.
     */
    fun execute(stocks: List<Stock>): Flow<List<Stock>> {

        val stockFlow:Flow<List<Stock>> = flow {
            emit(stocks)
            delay(1000)
            emit(stocks.shuffled()) // simulate stock update
        }

        val minPriceFilterFlow: Flow<Double> = flow {
            emit(50.0)
            delay(500)
            emit(100.0)
            delay(500)
            emit(150.0)
        }

        return stockFlow.combine(minPriceFilterFlow) {
            stockList,minPrice -> println("Recomputing for minPrice = $minPrice")
            stockList.filter { it.priceUsd >= minPrice }
        }
    }
}
```

```kotlin
package org.kotlinflowlearner.stockflow.usecases.uc16

import kotlinx.coroutines.runBlocking
import org.kotlinflowlearner.stockflow.csv.CsvStockLoader
import java.nio.file.Path

fun main(){

    runBlocking {
        val useCase = UC16Combine()

        val resource = requireNotNull(
            object {}.javaClass.classLoader.getResource("stocks.csv")
        )

        val path = Path.of(resource.toURI())

        val stocks = CsvStockLoader.load(path)

        useCase.execute(stocks).collect{
            filtered -> println("Filtered size: ${filtered.size}")
        }
    }
}
```

### **OUTPUT LOGS**

```kotlin
Recomputing for minPrice = 50.0
Filtered size: 15
Recomputing for minPrice = 100.0
Filtered size: 8
Recomputing for minPrice = 100.0
Filtered size: 8
Recomputing for minPrice = 150.0
Filtered size: 7
```

**What You Will Observe**

Timeline:

t = 0 → stock emits  
t = 0 → filter emits 50

→ combine emits result

t = 500 → filter emits 100

→ combine emits again

t = 1000 → stock emits updated list

→ combine emits again

t = 1500 → filter emits 150

→ combine emits again

**Important Point to Note:**

It reacts whenever either flow changes.

### What We Achieved

We created **Derived reactive state** from:

**Flow<List<Stock>> + Flow<Double>** into **Flow<List<Stock>>**

That is reactive composition.
