RxJava中的flatmap和switchmap有什么区别?


149

rxjava DOC switchmap的定义是相当含糊,并将其链接到同一页作为flatmap。两家运营商有什么区别?


1
关于它的链接与flatmap链接到同一页面。确实是这样 但是向下滚动到“ 特定语言的信息”部分,然后打开有趣的运算符。我认为应该从TOC自动完成此操作,但是...您也可以在javadoc中看到相同的图片。
Ruslan Stelmachenko

Answers:


180

根据文档(http://reactivex.io/documentation/operators/flatmap.html

switchMap是像flatMap直到一个新的事件被从源观察的发射它将只发射从可观察到的新的项目。

大理石图显示得很好。注意图中的差异:

switchMap第二个原始发射(绿色大理石)中,由于第三个原始发射(蓝色大理石)已经开始并且已经发射了其第一个映射发射(蓝色菱形),因此不发射其第二个映射发射(绿色正方形)。换句话说,只有两个映射的绿色排放中的第一个发生。没有发射出绿色方块,因为蓝色菱形击败了它。

在中flatMap,即使它们“过时”,也会发出所有映射结果。换句话说,这两个第一第二的映射绿色排放发生-一个绿色的方块会一直发出(如果他们使用一致的地图功能,因为他们没有,你看到的第二个绿钻,即使它被发射一颗蓝色钻石)

switchMap 在switchMap中,如果原始可观察物发出新的东西,则先前的排放不再产生映射的可观察物; 这是避免陈旧结果的有效方法

flatMap

在switchMap中,如果原始可观察物发出新的东西,则先前的排放不再产生映射的可观察物; 这是避免陈旧结果的有效方法


4
谢谢,该图非常有帮助。您是否知道使用switchMap的真实示例?
朱利安(Julian Go)

1
@JulianGo这里有一个示例:github.com/samuelgruetter/rx-playground/blob/master / ...它使用.map(func).switch,但与相同.switchMap(func)
塞缪尔·格鲁特

2
万一某人仍然需要switchMap的真实示例,他可以单击此链接链接,它将了解何时使用swicthMap而不是flatMap。
hermannovich '16

2
对于使用RxJs5使用SwitchMap从本莱什一个例子-见分钟25-26在这里- youtube.com/watch?v=3LKMwkuK0ZE 对我来说,flatmap已经明白...
arcseldon

7
大理石图显示得很好吗?什么?我想您是否已经了解switchmap。
Helzgate

166

我在实现“即时搜索”时遇到了这种情况-即,当用户在文本框中键入内容时,每次击键时结果几乎实时显示。解决方案似乎是:

  1. 具有一个主题,例如String的PublishSubject
  2. 在文本框更改回调中,调用.onNext(text)
  3. 将.debounce过滤器应用于速率限制服务器查询
  4. 应用.switchMap执行服务器查询-获取搜索词并返回Observable of SearchResponse
  5. 使用使用SearchResponse并更新UI的方法来应用.subscribe。

使用flatMap时,搜索结果可能会过时,因为搜索响应可能会不按顺序返回。为了解决这个问题,应该使用switchMap,因为它确保一旦提供了新的可观察对象,便取消订阅旧的可观察对象。

因此,总而言之,当所有结果都重要时,无论其时间如何,都应使用flatMap,而当仅来自最后一个Observable事项的结果时,应使用switchMap。


您可以在GitHub
Cabezas

95

没有flatMap讨论是不完整的比较和对比鲜明的switchMapconcatMapconcatMapEager

所有这些方法都采用a Func1将流转换为Observables,然后将其发出;区别在于返回的Observables 何时被订阅和取消订阅,以及是否以及何时Observable由所讨论的____Map运营商发出这些s的排放。

  • flatMap订阅尽可能多的发射Observable。(这是与平台有关的数字,例如,在Android上为较低的数字)。当订单不重要且您希望尽快排放时,请使用此数字。
  • concatMap订阅第一个,Observable并且仅Observable在前一个完成时订阅下一个。当订单很重要并且您想要节省资源时,请使用此选项。一个完美的例子是通过首先检查缓存来推迟网络呼叫。后面通常​​可能带有.first()或,.takeFirst()以避免进行不必要的工作。

    http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/

  • concatMapEager工作原理大致相同,但订阅的数量尽可能多(取决于平台),但仅在前一个Observable完成后才发出。当您需要完成许多并行处理,但又想保持原始顺序(与flatMap不同)时,它是完美的。

  • switchMap将订阅Observable它遇到的最后一个,并取消订阅所有之前Observable的。这对于诸如搜索建议之类的情况是完美的:用户更改了搜索查询后,旧的请求将不再受关注,因此不再订阅,并且行为良好的Api端点将取消网络请求。

如果返回的Observables不是subscribeOn另一个线程,则上述所有方法的行为可能都差不多。当您允许嵌套Observables在其自己的线程上执行操作时,就会出现有趣且有用的行为。然后,您可以从并行处理中获得很多好处,并智能地取消订阅或不订阅Observable不感兴趣您的Subscribers

  • amb可能也很有趣。给定任意数量的Observables,它发出的项目与第一个Observable发出任何东西的项目相同。当您有多个可能/应该返回同一事物并且想要性能的源时,这可能会很有用。例如排序,您可以amb使用合并排序来进行快速排序,并使用速度更快的那个。

1
If you are returning Observables that don't subscribeOn another thread, all of the above methods may behave much the same.- switchMap vs flatMap我以前遇到的每一个解释,都错过了这个重要方面,现在一切都更加清晰了。谢谢。
安迪·雷斯

55

switchMap 在RxJS 4中曾经被称为 flatMapLatest

它基本上只是传递最新的 Observable中的事件,而取消上一个中的订阅。


@EpicPandaForce尽管它与CombineLatest不一致,但它会在可观察到的源发出时(而不是一次发出)发出最新值。
Michael Fry

2
之所以称其为switchMap,部分原因是因为您可以使用o.map(...)。switch()自己实现此操作符。虽然那时我会想像是mapSwitch,它似乎不太容易滚开舌头。
Niall Connaughton

7

Map,FlatMap,ConcatMapSwitchMap应用功能或修改Observable发出的数据。

  • Map修改了源Observable发出的每个项目,并发出修改后的项目。

  • FlatMap,SwitchMapConcatMap还在每个发射的项目上应用了一个函数,但是它返回可再次发射数据的Observable自身,而不是返回修改后的项目。

  • FlatMapConcatMap的工作原理几乎相同。它们合并多个Observable发出的项目,并返回一个Observable。

  • FlatMapConcatMap之间的区别在于项目的发出顺序。
  • FlatMap可以在发射时交叉插入项目,即不保持发射的项目顺序。
  • ConcatMap保留项目的顺序。但是ConcatMap的主要缺点是,它必须等待每个Observable完成其工作,因此不能保持异步。
  • SwitchMapFlatMapConcatMap有点不同。每当开始发射新项目时,SwitchMap就会从先前的源Observable退订,因此总是从当前Observable发射项目。

1

如果您正在寻找示例代码

/**
 * We switch from original item to a new observable just using switchMap.
 * It´s a way to replace the Observable instead just the item as map does
 * Emitted:Person{name='Pablo', age=0, sex='no_sex'}
 */
@Test
public void testSwitchMap() {
    Observable.just(new Person("Pablo", 34, "male"))
              .switchMap(person -> Observable.just(new Person("Pablo", 0, "no_sex")))
              .subscribe(System.out::println);

}

您可以在这里查看更多示例https://github.com/politrons/reactive


4
但是您会错过switchMap与flatMap区别的关键功能-只有最新的Observable事项,而不再订阅以前的事项。
Artem Novikov

3
在此示例中,当您将其替换switchMapflatMap,它将完全相同。
Piotr Wittchen '18年

1

这是一个多于101行的示例。那为我解释了事情。

就像有人说的那样:它得到了最后一个可观察到的(如果可能的话,它是最慢的),而忽略了其余的。

结果是:

Time | scheduler | state
----------------------------
0    | main      | Starting
84   | main      | Created
103  | main      | Subscribed
118  | Sched-C-0 | Going to emmit: A
119  | Sched-C-1 | Going to emmit: B
119  | Sched-C-0 | Sleep for 1 seconds for A
119  | Sched-C-1 | Sleep for 2 seconds for B
1123 | Sched-C-0 | Emitted (A) in 1000 milliseconds
2122 | Sched-C-1 | Emitted (B) in 2000 milliseconds
2128 | Sched-C-1 | Got B processed
2128 | Sched-C-1 | Completed

您会看到A被忽略。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.