RxJava
map
flatMap
functional programming
reactive programming

When do you use map vs flatMap in RxJava?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

RxJava is a widely-used library for composing asynchronous and event-based programs using observable sequences for the Java platform. Two fundamental operators used in RxJava are map and flatMap. Both operators transform items emitted by an Observable, but their application contexts can be quite different. Understanding when to use each is crucial for writing effective and scalable reactive code.

What is map?

The map operator transforms each item emitted by an Observable by applying a function to it. It is a one-to-one transformation where each input item has a corresponding output item.

Example of map

Let's say we have a list of strings, and we want to transform them into their lengths.

java
1List<String> stringList = Arrays.asList("RxJava", "map", "flatMap");
2Observable.fromIterable(stringList)
3          .map(String::length)
4          .subscribe(length -> System.out.println("Length: " + length));
5
6// Output:
7// Length: 6
8// Length: 3
9// Length: 7

In this example, the function passed to map converts each string into its length, thereby transforming the emitted data from one form to another without altering the item's stream structure.

What is flatMap?

The flatMap operator, on the other hand, is used to transform the items emitted by an Observable into Observables themselves, then flatten the emissions from those Observables into a single Observable. This operator shines when the results of the transformation need to emit more than one item at each transformation step or are asynchronous.

Example of flatMap

Imagine we have a list of customer IDs, and for each ID, we need to fetch customer details asynchronously.

java
1Observable<Integer> customerIds = Observable.just(101, 102, 103);
2
3customerIds.flatMap(id -> getCustomerDetails(id))
4           .subscribe(details -> System.out.println(details));
5
6// Mocking an asynchronous call to fetch customer details using Observables
7private static Observable<String> getCustomerDetails(int id) {
8    return Observable.just("CustomerDetails for ID: " + id);
9}
10
11// Output:
12// CustomerDetails for ID: 101
13// CustomerDetails for ID: 102
14// CustomerDetails for ID: 103

Here, flatMap allows for asynchronous fetching of customer details and combines them into a single Observable stream.

Key Differences

Below is a table summarizing the key distinctions between map and flatMap.

FeaturemapflatMap
Transformation TypeOne-to-oneOne-to-many, flattening multiple streams into one
OutputTransformed itemsItems from multiple merged Observables
Use CaseSimple data transformationAsynchronous APIs, merging multiple asynchronous streams
Example Function SignatureFunction<T, R>Function<T, ObservableSource<R>>
ProcessingSynchronousCan be asynchronous
Stream StructurePreserved, transforms each item onlyNot preserved, may alter structure due to flattening

When to Use Which Operator

  1. Use map when:
    • You have a straightforward, one-to-one transformation.
    • The transformation is simple and doesn't require nested Observables.
    • Operations are synchronous and the structure of the stream is not intended to be altered.
  2. Use flatMap when:
    • The transformation results in multiple outputs per input.
    • You need to perform asynchronous operations such as network requests or database calls.
    • You want to flatten multiple Observables into a single observable stream.
    • The operation returns an Observable for each input item, which needs to be combined into one Observable.

Additional Considerations

  • Error Handling: Both map and flatMap operators support error handling by propagating errors downstream. However, handling errors with flatMap can have a broader impact due to the potential of multiple Observable streams.
  • Concurrency: When using flatMap, you can specify concurrency behavior to control how multiple Observables generated by it are merged. For example, you can limit the number of concurrently subscribed Observables to prevent overwhelming system resources.
  • Performance: While map generally performs better due to its simplified processing (single transformation), flatMap introduces overhead when managing multiple Observables. Understanding the performance implications can be critical in high-flow scenarios.

Conclusion

Choosing between map and flatMap hinges on understanding the requirements of data transformation and processing operations. Employ map for basic, synchronous transformations and flatMap to manage more complex, asynchronous scenarios. Mastering these concepts paves the way for creating efficient and effective reactive applications using RxJava.


Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.