Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When do you use map vs flatMap in RxJava?

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 the 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.

like image 458
Christopher Perry Avatar asked Apr 03 '14 19:04

Christopher Perry


People also ask

What's the difference between MAP and flatMap () in RxJava?

map: Transform the items emitted by this Flux by applying a synchronous function to each item. flatMap: Transform the elements emitted by this Flux asynchronously into Publishers.

What is difference between MAP and flatMap in java8?

The map() method wraps the underlying sequence in a Stream instance, whereas the flatMap() method allows avoiding nested Stream<Stream<R>> structure. Here, map() produces a Stream consisting of the results of applying the toUpperCase() method to the elements of the input Stream: List<String> myList = Stream.

What is switchMap in RxJava?

switchMaplinkProjects each source value to an Observable which is merged in the output Observable, emitting values only from the most recently projected Observable.

What is flatMapObservable?

flatMapObservable. Observable. returns an Observable that is the result of a function applied to an item emitted by a Single. from. Single.


2 Answers

map transform one event to another. flatMap transform one event to zero or more event. (this is taken from IntroToRx)

As you want to transform your json to an object, using map should be enough.

Dealing with the FileNotFoundException is another problem (using map or flatmap wouldn't solve this issue).

To solve your Exception problem, just throw it with a Non checked exception : RX will call the onError handler for you.

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) {             // this exception is a part of rx-java             throw OnErrorThrowable.addValueAsLastCause(e, file);         }     } }); 

the exact same version with flatmap :

Observable.from(jsonFile).flatMap(new Func1<File, Observable<String>>() {     @Override public Observable<String> call(File file) {         try {             return Observable.just(new Gson().toJson(new FileReader(file), Object.class));         } catch (FileNotFoundException e) {             // this static method is a part of rx-java. It will return an exception which is associated to the value.             throw OnErrorThrowable.addValueAsLastCause(e, file);             // alternatively, you can return Obersable.empty(); instead of throwing exception         }     } }); 

You can return too, in the flatMap version a new Observable that is just an error.

Observable.from(jsonFile).flatMap(new Func1<File, Observable<String>>() {     @Override public Observable<String> call(File file) {         try {             return Observable.just(new Gson().toJson(new FileReader(file), Object.class));         } catch (FileNotFoundException e) {             return Observable.error(OnErrorThrowable.addValueAsLastCause(e, file));         }     } }); 
like image 177
dwursteisen Avatar answered Oct 19 '22 21:10

dwursteisen


FlatMap behaves very much like map, the difference is that the function it applies returns an observable itself, so it's perfectly suited to map over asynchronous operations.

In the practical sense, the function Map applies just makes a transformation over the chained response (not returning an Observable); while the function FlatMap applies returns an Observable<T>, that is why FlatMap is recommended if you plan to make an asynchronous call inside the method.

Summary:

  • Map returns an object of type T
  • FlatMap returns an Observable.

A clear example can be seen here: http://blog.couchbase.com/why-couchbase-chose-rxjava-new-java-sdk .

Couchbase Java 2.X Client uses Rx to provide asynchronous calls in a convenient way. Since it uses Rx, it has the methods map and FlatMap, the explanation in their documentation might be helpful to understand the general concept.

To handle errors, override onError on your susbcriber.

Subscriber<String> mySubscriber = new Subscriber<String>() {     @Override     public void onNext(String s) { System.out.println(s); }      @Override     public void onCompleted() { }      @Override     public void onError(Throwable e) { } }; 

It might help to look at this document: http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/

A good source about how to manage errors with RX can be found at: https://gist.github.com/daschl/db9fcc9d2b932115b679

like image 27
1vand1ng0 Avatar answered Oct 19 '22 22:10

1vand1ng0