Back

Explore Courses Blog Tutorials Interview Questions
0 votes
3 views
in Java by (10.2k points)

When do you use map vs flatMap in RxJava?

Say for example, we want to map Files containing JSON into Strings that contain the JSON--

Using map, we have to deal with the Exception somehow. But how?:

Observable.from(jsonFile).map(new Func1<File, String>() {

    @Override public String call(File file) {

        try {

            return new Gson().toJson(new FileReader(file), Object.class);

        } catch (FileNotFoundException e) {

            // So Exception. What to do ?

        }

        return null; // Not good :(

    }

});

Using flatMap, it's much more verbose, but we can forward the problem down the chain of Observables and handle the error if we choose somewhere else and even retry:

Observable.from(jsonFile).flatMap(new Func1<File, Observable<String>>() {

    @Override public Observable<String> call(final File file) {

        return Observable.create(new Observable.OnSubscribe<String>() {

            @Override public void call(Subscriber<? super String> subscriber) {

                try {

                    String json = new Gson().toJson(new FileReader(file), Object.class);

                    subscriber.onNext(json);

                    subscriber.onCompleted();

                } catch (FileNotFoundException e) {

                    subscriber.onError(e);

                }

            }

        });

    }

});

I like the simplicity of map, but the error handling of flatmap (not the verbosity). I haven't seen any best practices on this floating around and I'm curious how this is being used in practice.

1 Answer

0 votes
by (46k points)

Here is a simple thumb-rule that I use help me decide as when to use flatMap() over map() in Rx's Observable.

Once you come to a decision that you're going to employ a map transformation, you'd write your transformation code to return some Object right?

If what you're returning as end result of your transformation is:

  • a non-observable object then you'd use just map(). And map() wraps that object in an Observable and emits it.
  • an Observable object, then you'd use flatMap(). And flatMap() unwraps the Observable, picks the returned object, wraps it with its own Observable and emits it.

Say for example we've a method titleCase(String inputParam) that returns Titled Cased String object of the input param. The return type of this method can be String or Observable<String>.

  • If the return type of titleCase(..) were to be mere String, then you'd use map(s -> titleCase(s))
  • If the return type of titleCase(..) were to be Observable<String>, then you'd use flatMap(s -> titleCase(s))

Hope that clarifies.

Related questions

0 votes
2 answers
0 votes
2 answers
0 votes
1 answer
0 votes
1 answer
asked Jul 13, 2019 in Java by Shubham (3.9k points)

Browse Categories

...