RxJava flatMap, switchMap, concatMap

Filed Under: RxJava
rxjava-flatmap-flow

In this tutorial, we’ll be looking into three important map operators in RxJava. FlatMap, SwitchMap, ConcatMap add more power to the already powerful RxJava framework of operators.

RxJava FlatMap

A map operator transforms each of the values from the Observable sequence.
A flatmap operator is used to transform an observable by breaking it into smaller observables containing individual values from the first observable. Then you do stuff on the new observables and finally, the flatmap merges these single observables into one complete observable.
The new observable is now transformed.
FlatMap flattens an observable into single observables which are modified and merged into a new observable.
The new observable that comes out of the flatMap doesn’t guarantee you the same order. The values are interleaved.

A FlatMap emits Observables instead of values

An illustration for the RxJava documentation is given below.
rxjava flatmap flow

What exactly does a FlatMap do?
A FlatMap divides an Observable into many singular Observables. Hence, instead of sending each of the Observable values one by one, a FlatMap does everything in parallel and then merges the results in whatever order they are completed.

Let’s look at an example of FlatMap by creating a new IntelliJ java project and adding the RxJava dependency in the build.gradle.


import rx.Observable;
import rx.functions.Func1;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class RxOperatorMaps {


    public static void main(String[] args) throws InterruptedException {
        final List<String> race = new ArrayList<>(Arrays.asList("Alan", "Bob", "Cobb", "Dan", "Evan", "Finch"));



        Observable.from(race)
                .flatMap(new Func1<String, Observable<?>>() {
                    @Override
                    public Observable<?> call(String s) {
                        final int delay = new Random().nextInt(5);
                        return Observable.just(s).map(String::toUpperCase)
                                .delay(delay, TimeUnit.SECONDS);
                    }
                })
                .subscribe(System.out::println);

        Thread.sleep(5000);
    }
}

//Prints
//BOB
//FINCH
//ALAN
//EVAN
//COBB
//DAN
  • The flatMap applies a function to each observable emitted. The function type is a unit of the source observable type(String in this case) and a new Observable with the type you transform it into.
  • In the above code, a String observable is emitted from the source which was a List of Strings observable.
  • The new observables are delayed here to show you that a flatMap merges the single observables in the order in which they complete.
  • We’ve used a delay operator which delays the emission by a random number of seconds.
  • We’ve set the main thread to sleep for 5 seconds to prevent the main function from returning while the Observables are still doing their work.

Note: A flatMap implicitly contains the merge operator too.

Difference between a map and a flatMap operator
Map returns an object of type T whereas a FlatMap returns an Observable<T>.

Using an observable operator we can also filter down the number of values we want to reach the observer.


Observable.from(race)
                .flatMap(s -> {
                    final int delay = new Random().nextInt(5);

                    if (s.contains("a"))
                        return Observable.empty()
                                .delay(delay, TimeUnit.SECONDS);
                    else
                        return Observable.just(s).map(String::toUpperCase)
                                .delay(delay, TimeUnit.SECONDS);
                })
                .subscribe(System.out::println);

        Thread.sleep(5000);

//Prints
//FINCH
//COBB
//BOB

flatMap would be useful in android when you need to perform multiple network requests in parallel.

RxJava SwitchMap

A SwitchMap flattens the source observable but only returns the last emitted single observable.
The below illustration followed by example demonstrates what the above line means.

rxjava switchMap


Observable.from(race)
                .switchMap((Func1<String, Observable<?>>) s -> {
                    final int delay = new Random().nextInt(2);
                    return Observable.just(s).map(String::toUpperCase)
                            .delay(delay, TimeUnit.SECONDS);
                })
                .subscribe(System.out::println);

        Thread.sleep(5000);

//Prints for me. It can differ for you since it's random.
//ALAN
//EVAN
//FINCH

SwitchMap would emit only the latest observable after a particular delay. It ignores all the previous ones.
It is useful when it comes to retrieving the latest data from a feed. It’s useful when you need to identify the latest among many feeds.

RxJava concatMap

If you’ve read flatMap you almost know what a concatMap operator is. It is similar to a flatMap except that it keeps the order of the observables.
To keep the order, it needs to wait for one observable to finish before proceeding to the next, thereby breaking away from the asynchronous concept and making the task longer than usual.
Another difference between flatMap and concatMap operators
The flatMap uses merge operator implicitly whereas concatMap uses concat operator.


Observable.from(race)
                .concatMap((Func1<String, Observable<?>>) s -> {
                    final int delay = new Random().nextInt(4);
                    return Observable.just(s).map(String::toUpperCase)
                            .delay(delay, TimeUnit.SECONDS);
                })
                .subscribe(System.out::println);

        Thread.sleep(5000);

//Prints
//ALAN
//BOB
//COBB

Why did it not print all the values?
Well it took so long that the main thread woke up and exited the main method. You can increase the thread sleep time or decrease the delay random number to view all.
But you get the concept right? ConcatMap takes longer. Use it only if you need the same sequence.

Reference: RxJava docs

Comments

  1. aaaaaaaa bbbbbbbb says:

    Map returns an object of type T whereas a FlatMap returns an Observable ?

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages