RxJava中flatmap和switchmap有什么区别?

时间:2015-01-27 16:51:15

标签: reactive-programming rx-java

switchmap的rxjava doc定义相当模糊,并将same page作为flatmap链接。两个运营商之间有什么区别?

7 个答案:

答案 0 :(得分:161)

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

switchMap就像flatMap它只会从新的observable中发出项目,直到从源可观察对象发出新事件为止。

大理石图表很好地展示了它。 请注意图中的差异:

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

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

<强> switchMap in switchMap if the original observable emits something new, previous emissions no longer produce mapped observables; this is an effective way to avoid stale results

<强> flatMap

in switchMap if the original observable emits something new, previous emissions no longer produce mapped observables; this is an effective way to avoi stale results

答案 1 :(得分:161)

我在实施&#34;即时搜索&#34;时遇到了这个问题。 - 即当用户在文本框中键入时,结果与每个键击几乎实时地出现。解决方案似乎是:

  1. 有一个主题,例如PublishSubject of String
  2. 在文本框中更改回调,调用.onNext(文本)
  3. 将.debounce过滤器应用于速率限制服务器查询
  4. 应用.switchMap执行服务器查询 - 获取搜索词并返回SearchResponse的Observable
  5. 将.subscribe应用于使用SearchResponse并更新UI的方法。
  6. 使用flatMap时,搜索结果可能过时,因为搜索响应可能会无序返回。要解决这个问题,应该使用switchMap,因为它可以确保在提供较新的observable时,取消订阅旧的observable。

    因此,总而言之,当所有结果都重要时,应该使用flatMap,而不管它们的时间如何,只有当只有最后一个Observable事件的结果时才应该使用switchMap。

答案 2 :(得分:85)

在没有与switchMapconcatMapconcatMapEager进行比较和对比的情况下,没有完成flatMap讨论。

所有这些方法都会使用Func1将流转换为Observable s然后发出;不同之处在于返回的Observable订阅和取消订阅的时间,以及Observable运算符发出的____Map s的排放量是否及何时。

  • flatMap订阅了尽可能多的Observable个{}。 (这是依赖于平台的号码。例如Android上的较低号码)当订单不重要时,请使用此选项,并且您要尽快排放。
  • concatMap订阅了第一个Observable,并且仅在前一个Observable完成时订阅了下一个.first()。当订单很重要并且您想节省资源时使用此选项。一个完美的例子是通过首先检查缓存来推迟网络呼叫。通常可以跟.takeFirst()concatMapEager,以避免做不必要的工作。

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

  • Observable的工作方式大致相同,但订阅的数量尽可能多(取决于平台),但只会在之前的switchMap完成后才会发出。当你需要进行大量的并行处理时,这是完美的,但是(与flatMap不同)你想保持原始的顺序。

  • Observable将订阅其遇到的最后一次Observable,并取消订阅之前的所有Observable。这非常适合搜索建议等情况:一旦用户更改了搜索查询,旧请求就不再有任何兴趣,因此取消订阅,行为良好的Api端点将取消网络请求。

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

  • Observable也可能是有意义的。给定任意数量的Observable s,它会发出与发出任何内容的第一个amb相同的项目。 当你有多个源可以/应该返回相同的东西并且你想要性能时,这可能很有用。例如排序,您可以{{1}}使用合并排序进行快速排序,并使用更快的排序。

答案 3 :(得分:53)

RxJS 4中的

switchMap was once called flatMapLatest

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

答案 4 :(得分:3)

地图,FlatMap,ConcatMap SwitchMap 应用功能或修改Observable发出的数据。

  • 地图修改由源Observable发出的每个项目,并发出修改后的项目。

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

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

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

答案 5 :(得分: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

答案 6 :(得分:1)

这是另一个 - 101行长example。这解释了我的事情。

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

结果:

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被忽略了。