Difference Between Flatmap and Switchmap in RxJava – RxJava中Flatmap和Switchmap的区别

最后修改: 2018年 8月 24日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

RxJava provides various operators to transform items emitted by an observable into other observables. Two of the most popular operators are flatMap and switchMap. The difference between the two is often hard to understand for beginners in reactive programming.

RxJava提供了各种操作符,可以将一个可观察对象发出的项目转化为其他可观察对象。其中最流行的两个操作符是flatMapswitchMap。对于反应式编程的初学者来说,这两者之间的区别往往很难理解。

For an introduction to RxJava, refer to this article.

关于RxJava的介绍,请参考这篇文章

In this tutorial, we’ll understand the difference by walking through a simple example.

在本教程中,我们将通过一个简单的例子来了解其中的区别。

2. flatMap

2.flatMap

The flatMap operator converts each item returned from a source observable into an independent observable using the supplied function and then merges all the observables into a single observable. The order in which observables are merged isn’t guaranteed to be the same as in the source Observable.

flatMap操作符使用提供的函数将从源观测器返回的每个项目转换为独立的观测器,然后将所有的观测器合并为一个观测器。观察变量被合并的顺序并不保证与源Observable.中的相同。

Let’s take a search engine as an example. Consider that we want to display search results immediately after we type in each character of the word:

让我们以一个搜索引擎为例。考虑到我们想在输入每个单词的字符后立即显示搜索结果。

For simplicity’s sake, we have taken the search query input as a list of words.

为了简单起见,我们把搜索查询的输入作为一个词的列表。

Also, we always return two search results for each word.

另外,我们总是为每个词返回两个搜索结果。

// given
List<String> actualOutput = new ArrayList<>();
TestScheduler scheduler = new TestScheduler();
List<String> keywordToSearch = Arrays.asList("b", "bo", "boo", "book", "books");

// when
Observable.fromIterable(keywordToSearch)
  .flatMap(s -> Observable.just(s + " FirstResult", s + " SecondResult")
    .delay(10, TimeUnit.SECONDS, scheduler))
  .toList()
  .doOnSuccess(s -> actualOutput.addAll(s))
  .subscribe();

scheduler.advanceTimeBy(1, TimeUnit.MINUTES);

// then
assertThat(actualOutput, hasItems("b FirstResult", "b SecondResult",
  "boo FirstResult", "boo SecondResult",
  "bo FirstResult", "bo SecondResult",
  "book FirstResult", "book SecondResult",
  "books FirstResult", "books SecondResult"));

Please note that the order isn’t always the same with every run.

请注意,每次运行的顺序并不总是相同。

3. switchMap

3.switchMap

The switchMap operator is similar to flatMap, except that it retains the result of only the latest observable, discarding the previous ones.

switchMap操作符与flatMap类似,只是它只保留最新的观察结果,而抛弃之前的观察结果。

Let’s change our requirement in that we want to get search results for only the final fully-formed word (in this case, “books”) and not for the partial query strings. To achieve this, we can use switchMap.

让我们改变一下我们的要求,即我们只想获得最后的全称词(在本例中是 “books”)的搜索结果,而不是部分查询字符串。为了实现这一点,我们可以使用switchMap

If we just replace flatMap with switchMap in the above code example, the following assertions would be valid:

如果我们只是在上面的代码例子中用switchMap替换flatMap,下面的断言将是有效的。

assertEquals(2, actualOutput.size());
assertThat(actualOutput, hasItems("books FirstResult", "books SecondResult"));

As we see here, we only got a single observable containing the latest input item from the source observable. All previous results were discarded.

正如我们在这里看到的,我们只得到了一个包含源观测器的最新输入项的单一观测器。之前的所有结果都被丢弃了。

4. Conclusion

4. 结论

To summarize, switchMap differs from flatMap in that it only retains the output of applying a provided function to the latest item emitted by the source Observable, flatMap, on the other hand, retains all results and returns them in an interleaved manner without guaranteeing order.

总而言之,switchMapflatMap的不同之处在于,它只保留对源Observable发出的最新项目应用所提供的函数的输出,而flatMap则保留所有结果并以交错的方式返回,不保证顺序。

As always, the code used in this article is available over on GitHub.

一如既往,本文中使用的代码可在GitHub上找到。