In this article, we will look into an example of RxJava map operator. We have seen in our last article the relation between an Observable and Observer, and how an Observable starts emitting items to an Observer as soon as it subscribes to the Observable. If want the Observer to receive a different flavour of the item by applying a function to each emitted item then we need to build a new Observable using the map operator and the function that transforms the item.
Map
In the below marble diagram, we show the emitted item being transformed by the mapper function. On the other side of the mapper function, there is the Observer that receives the transformed item.
Map Example
In the below example, we have a list of subjects. Each subject has a list of topics. We use the map operator to convert the Observable emitting subjects to an Observable that emits the topics covered related to the subject.
rx.Observable.from(SUBJECTS) .map(new Func1<String, List<String>>() { @Override public List<String> call(String subj) { topicCountBySubject.put(subj, TOPICS_BY_SUBJECT.get(subj).size()); return TOPICS_BY_SUBJECT.get(subj); } })
Once map()
is applied, a new Observable
is created that depends on a new OnSubscribe
function that knows the source Observable
and the mapper function.
ObservableMapExample:
package com.javarticles.rx; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import rx.functions.Action0; import rx.functions.Action1; import rx.functions.Func1; public class ObservableMapExample { private static final List<String> SUBJECTS = new ArrayList<>(); static { SUBJECTS.add("Java"); SUBJECTS.add("Db"); SUBJECTS.add("Spring"); } private static final Map<String, List<String>> TOPICS_BY_SUBJECT = new HashMap<>(); static { TOPICS_BY_SUBJECT.put("Java", Arrays.asList("Concurrency", "Generics")); TOPICS_BY_SUBJECT.put("Db", Arrays.asList("Performance", "SQL")); TOPICS_BY_SUBJECT.put("Spring", Arrays.asList("IOC", "proxy", "beanFactory")); } public static void main(String[] args) { final Map<String, Integer> topicCountBySubject = new HashMap<>(); final List<String> allTopics = new ArrayList<>(); rx.Observable.from(SUBJECTS) .map(new Func1<String, List<String>>() { @Override public List<String> call(String subj) { topicCountBySubject.put(subj, TOPICS_BY_SUBJECT.get(subj).size()); return TOPICS_BY_SUBJECT.get(subj); } }).subscribe(new Action1<List<String>>() { @Override public void call(List<String> topics) { allTopics.addAll(topics); } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { } }, new Action0() { @Override public void call() { System.out.println("All topics: " + allTopics); System.out.println("Topics count: " + topicCountBySubject); } }); } }
In the subscriber’s onNext()
callback, we simply add up all the topics. In the mapper function, we build new data which tracks the number of topics that each subject deals with.
Output:
All topics: [Concurrency, Generics, Performance, SQL, IOC, proxy, beanFactory] Topics count: {Java=2, Spring=3, Db=2}
Map Observable
In the below sequence diagram, we show how map()
operator results in a new Observable
that now depends on a new OnSubscriber
called OnSubscriberMap
that knows the source Observable
, actual subscriber and the mapper function.
Map subscribe sequence
In the below diagram, we show the sequence flow that follows when an Observer subscribes to the mapped Observable
. As you can see the emitted item is first transformed by the mapper function before delegating to the actual subscriber.
Download the source code
This was an example about RxJava Map.