Transforming Operators

In this lesson, you’ll explore transforming operators. These operators let you manipulate and reshape the data flowing through your streams. You’ll cover the following operators:

  • map: This operator transforms each item into a flow. It’s similar to the map function in other collections, letting you apply a function to each element to create a new flow.
  • flatMapLatest: This operator allows you to create a new flow from each item in an existing flow. It’s useful when you need to work with asynchronous tasks or nested data structures.
  • transform: This operator allows you to perform various operations like emitting multiple values, skipping emissions, or applying more complex logic on each item in the flow.

The map Operator

Suppose you’re processing a stream of carrots in your factory, and you need to convert them into carrot juice. You could use the map operator to transform each carrot into a juice object:

fun carrotJuice(): Flow<CarrotJuice> = carrots.asFlow()
  .map { carrot -> carrotJuicer.toJuice(carrot) }
  .collect { juice -> println("Produced: $juice") }

The map operator takes a function that transforms each item into a new form, in this case, creating a CarrotJuice object from a carrot.

The flatMapLatest Operator

Next, suppose you have a collection of carrot batches, and each batch has some number of carrots. You process each carrot from the batch, but if a new batch arrives, you switch to that one:

fun processedCarrots(): Flow<Carrot> = batches.asFlow()
  .flatMapLatest { batch -> batch.carrots.asFlow() }
  .map { carrot -> processCarrot() }
  .collect { carrot -> println("Processed $carrot") }

The flatMapLatest operator creates a new flow from each item in the source flow, but the previous flow is canceled if the original flow produces a new value.

The transform Operator

Finally, imagine you have a flow of carrots, and you need to check their quality. You only want to emit the high-quality ones for further processing.

fun processedCarrots(): Flow<Carrot> = carrots.asFlow()
  .transform { carrot ->
    if (carrot.isHighQuality) {
      emit(carrot) // Emit only high-quality carrots
      println("High-quality carrot detected: ${carrot.id}")
    } else {
      println("Discarding low-quality carrot: ${carrot.id}")
    }
  }
  .collect { carrot ->
    println("Processing carrot: ${carrot.id}")
  }

The transform operator offers low-level control over what gets emitted, making it highly versatile. It accepts a lambda function, which gives you full control over how to manipulate the flow’s data.

Wrap-Up

In this lesson, you’ve explored key transforming operators in Kotlin Flow, including map, flatMapLatest, and transform. You’ve seen how these operators can be used to manipulate and transform data as it flows through your reactive streams.

In the next lesson, you’ll see a demonstration using these transforming operators in action.

See forum comments
Download course materials from Github
Previous: Introduction Next: Transforming Operators Demo