簡體   English   中英

RxJava 中的 concatMap 和 flatMap 有什么區別

[英]What is the difference between concatMap and flatMap in RxJava

看起來這兩個功能非常相似。 它們具有相同的簽名(接受rx.functions.Func1<? super T, ? extends Observable<? extends R>> func ),並且它們的rx.functions.Func1<? super T, ? extends Observable<? extends R>> func圖看起來完全相同。 無法在此處粘貼圖片,但這里是concatMap 的一張,這是flatMap的一張。 結果Observable的描述似乎有一些細微的差異,其中concatMap生成的包含連接結果 Observable 的項目,而flatMap生成的項目包含首先合並生成的 Observable 並發出結果的項目那個合並。

然而,我完全不清楚這種微妙之處。 任何人都可以更好地解釋這種差異,並且最好給出一些說明這種差異的例子。


正如您所寫,這兩個函數非常相似,細微的區別在於輸出的創建方式(在應用映射函數之后)。

平面地圖使用合並運算符,而 concatMap 使用concat 運算符

如您所見, concatMap 輸出序列是有序的 - 第一個 Observable 發出的所有項目在第二個 Observable 發出的任何項目之前發出,
當 flatMap 輸出序列被合並時 - 合並的 Observable 發出的項目可能以任何順序出現,無論它們來自哪個源 Observable。

盡管這里的答案很好,但如果沒有示例,也不容易發現差異。 因此,我為此創建了一個簡單的示例:

@Test
public void flatMapVsConcatMap() throws Exception {
    System.out.println("******** Using flatMap() *********");
    Observable.range(1, 15)
            .flatMap(item -> Observable.just(item).delay(1, TimeUnit.MILLISECONDS))
            .subscribe(x -> System.out.print(x + " "));

    Thread.sleep(100);

    System.out.println("\n******** Using concatMap() *********");
    Observable.range(1, 15)
            .concatMap(item -> Observable.just(item).delay(1, TimeUnit.MILLISECONDS))
            .subscribe(x -> System.out.print(x + " "));

    Thread.sleep(100);
}

******** 使用 flatMap() *********

1 2 3 4 5 6 7 9 8 11 13 15 10 12 14

******** 使用 concatMap() *********

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

從輸出中可以看出, flatMap的結果是無序的,而concatMap的結果是無序的。

一個非常重要的區別: concatMap等待當前發出的 observable 完成而flatMap不會。 flatMap嘗試盡可能多地啟動。 簡單地說 - 你不能連接無限的東西。 只需確保您在concatMap發出的concatMap可以完成,否則整個流程將卡住等待當前 observable 完成以連接下一個。

我發現大多數贊成的答案中的例子不太清楚,所以我發布了一個幫助我理解 flatMap 和 concatMap 之間區別的例子。

FlatMap需要排放源可觀察到的,然后創建新觀察到的,其合並到原來的鏈條,而concatMap它Concat的原始鏈。

主要區別在於 concatMap() 將按順序合並每個映射的 Observable 並一次觸發一個。 只有當當前 Observable 調用 onComplete() 時,它才會移動到下一個 Observable。

這是flatMap示例:

private void flatMapVsConcatMap() throws InterruptedException {
    Observable.just(5, 2, 4, 1)
            .flatMap(
                    second ->
                            Observable.just("Emit delayed with " + second + " second")
                                    .delay(second, TimeUnit.SECONDS)
            )
            .subscribe(
                    System.out::println,
                    Throwable::printStackTrace
            );

    Thread.sleep(15_000);
}

將導致:

發射延遲 1 秒
發射延遲 2 秒
發射延遲 4 秒
發射延遲 5 秒

這是concatMap示例:

private void flatMapVsConcatMap() throws InterruptedException {
    Observable.just(5, 2, 4, 1)
            .concatMap(
                    second ->
                            Observable.just("Emit delayed with " + second + " second")
                                    .delay(second, TimeUnit.SECONDS)
            )
            .subscribe(
                    System.out::println,
                    Throwable::printStackTrace
            );

    Thread.sleep(15_000);
}

將導致:

發射延遲 5 秒
發射延遲 2 秒
發射延遲 4 秒
發射延遲 1 秒

注意使用 Thread.sleep()因為delay()默認在計算調度器上運行

首先,flatMap 與 Rxjs 中的 mergeMap 相同。 所以這少了一種混淆。 所以有兩個 observable..

1) o1:來自(['Kitty','Donald','Batman']) 的簡單項目列表

2) process_o1(): process_o1() 是一個函數,它接受一個參數“item”並用它做一些事情並返回一個 Observable,它在完成時發出“done with [item]”。

o1.pipe(mergeMap(item => process_o1(item))).subscribe(data => {
console.log(data);
});

在這里,我們將看到:- 用 Kity 完成。

完成與唐納德。

完成與蝙蝠俠。

不能保證凱蒂先於唐納德,唐納德先於蝙蝠俠。 這是因為,一旦外部 observable 發出一個項目,內部 observable 就會被訂閱。

=== 但是在 concatMap 的情況下:-

o1.pipe(concatMap(item => process_o1(item))).subscribe(data => {
console.log(data);
});

我們有以下順序的保證:-

與凱蒂完成。

完成與唐納德。

完成與蝙蝠俠。

因為,使用 concatMap 運算符,在前一個內部 Observable 返回之前,內部 Observable 不會被訂閱。

外部 observable 可以自由地繼續並發出它的所有值,但是 concatMap 將確保它一個一個地處理這些值中的每一個並保持順序。 因此名稱為 concatMap。

關鍵是,如果你熱衷於維護做事的順序,你應該使用concatMap。 但是如果你不關心順序,你可以繼續使用 mergeMap 它會立即訂閱所有內部 Observables 並在它們返回時繼續發出值。

flatMap 與 concatMap

flatMap - 合並 - 如果發出新項目,則它具有優先級

concatMap - 連接 - 添加到最后 - 發出完整序列,只有在那之后(前一個完成)才能發出下一個序列

[地圖與平面地圖]

其他人已經指出了答案,但如果不是太明顯,則可能會使用 flatMap 創建不需要的並行性,如果不需要,您可以使用 concatMap 或重載flatMap(Function<? super T,? extends Publisher<? extends V>> mapper, int concurrency)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM