在 RxJava 中,latmap 和 switchmap 有什么区别?

交换图的 Rxjava 文档定义相当模糊,它以平面图的形式链接到 一致。这两个操作符之间的区别是什么?

68079 次浏览

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

switchMap类似于 flatMap但是,它只会从新的可观测数据中发出条目,直到一个新的事件从源可观测数据中发出。

大理石图显示得很清楚。 注意图表中的不同之处:

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

flatMap中,所有映射的结果都将被发出,即使它们是“过时的”。换句话说,都有第一个 还有第二个 地图绿色发射发生-一个 绿色方块将被发射(如果他们使用一致的映射功能; 因为他们没有,你看到的 第二绿色钻石,即使它是发射 之后第一蓝色钻石)

交换地图 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

平面地图

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. 有一个主题,如 PublishSubject of String
  2. 在文本框中,更改回调,调用.onNext (text)
  3. 退出过滤器以限制服务器查询的速率
  4. SwitchMap 来执行一个服务器查询——获取搜索词并返回 SearchResponse 的 Observer
  5. 使用使用 SearchResponse 并更新用户界面的方法来订阅。

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

因此,总的来说,当所有结果都重要时,不管它们的时间如何,都应该使用 latMap,而当只有最后一个可观察到的结果时,才应该使用 switchMap。

RxJS4中的 switchMap 曾被称为 最新地图

它基本上只是传递来自 最新的可观察事件的事件,并取消前一个事件的订阅。

如果没有与 switchMapconcatMapconcatMapEager进行比较和对比,就没有一个 latMap 讨论是完整的。

所有这些方法都采用 Func1,将流转换为 Observable,然后发射; 区别在于返回的 Observable何时被认购和取消认购,以及这些 Observable的发射是否以及何时由有关的 ____Map操作员发射。

  • flatMap订阅尽可能多的发出的 Observable。(这是一个依赖于平台的数字。当订单不重要,你希望尽快排放的时候使用这个。
  • concatMap订阅了第一个 Observable,只有在前一个 Observable完成时才订阅下一个 Observable。当订单很重要并且你想节约资源的时候使用它。一个完美的例子是通过首先检查缓存来推迟网络调用。通常紧接着是 .first().takeFirst(),以避免做不必要的工作。

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

  • concatMapEager的工作原理大致相同,但是订阅了尽可能多的内容(平台依赖) ,但是只有在前一个 Observable完成后才会发出。当您需要完成大量并行处理,但是(不同于 latMap)您希望保持原始顺序时,这种方法非常完美。

  • switchMap将订阅它遇到的最后一个 Observable,并取消所有以前的 Observable的订阅。这对于像搜索建议这样的情况来说是完美的: 一旦用户改变了他们的搜索查询,旧的请求就不再有任何意义,所以它不再被订阅,并且一个表现良好的 Api 端点将取消网络请求。

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

  • amb也可能是令人感兴趣的。给定任意数量的 Observable,它会发出与第一个发出任何东西的 Observable相同的项目。 当您拥有多个可以/应该返回相同内容的源并且希望获得性能时,这可能很有用。例如,排序,你可能 amb一个快速排序与合并排序,并使用任何更快。

如果您正在查找示例代码

/**
* 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

这是一个更多-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 被忽略了。

Map、 FlatMap、 ConcatMap 交换地图应用一个函数或修改观察器发出的数据。

  • Map 修改了由源可观察发出的每个条目,并发出修改后的条目。

  • FlatMap、 Switch Map 连接地图也对每个发出的条目应用一个函数,但是它不返回修改后的条目,而是返回可以再次发出数据的 Observer able 本身。

  • FlatMap 连接地图的工作原理大致相同,它们合并由多个可观测数据发出的项目,并返回单个可观测数据。

  • 平面地图连接地图之间的区别在于发出项目的顺序。
  • FlatMap 可以在发出时交错项目,即不维护发出的项目顺序。
  • ConcatMap 保留项目的顺序。但是 ConcatMap 的主要缺点是,它必须等待每个可观察对象完成其工作,因此不能维护异步。
  • Switch Map 平面地图连接地图略有不同。无论何时新项目开始发出,交换地图都会从以前的源可观测数据库中取消订阅,因此总是从当前的可观测数据库中发出项目。