Подтвердить что ты не робот

В чем разница между concatMap и flatMap в RxJava

Кажется, что эти 2 функции довольно похожи. Они имеют одну и ту же подпись (принимают rx.functions.Func1<? super T, ? extends Observable<? extends R>> func), а их мраморные диаграммы выглядят точно так же. Невозможно вставить фотографии здесь, но здесь один для concatMap, и здесь один для flatMap. Кажется, что в описании результирующего Observable есть некоторая тонкая разница, в которой один из выражений concatMap содержит элементы, которые являются результатом объединения результатов Observables, а результат, созданный flatMap, содержит элементы, которые являются результатом первого слияния полученных Observables, и испускает результат этого слияния.

Однако эта тонкость для меня совершенно неясна. Может ли кто-нибудь дать лучшее объяснение этой разницы и в идеале дать несколько примеров, иллюстрирующих эту разницу.

4b9b3361

Ответ 1


Как вы писали, две функции очень схожи, и тонкая разница заключается в том, как создается результат (после применения функции сопоставления).

В плоской карте используется оператор слияния, тогда как concatMap использует оператор concat.

Как вы видите, последовательность заказов concatMap упорядочена - все элементы, испускаемые первым наблюдаемым, испускаются перед любым из элементов, испускаемых вторым наблюдаемым,
в то время как последовательная последовательность flatMap объединяется - элементы, испускаемые объединенным Observable, могут отображаться в любом порядке, независимо от того, из какого источника Observable они пришли.

Ответ 2

Одно очень важное различие: concatMap ожидает, что ток, испускаемый наблюдаемым, завершен, а flatMap - нет. flatMap пытается запустить как можно больше. Просто сказано - вы не можете конкатенировать что-то бесконечное. Просто убедитесь, что наблюдаемые, которые вы испускаете в concatMap, можете завершить, иначе весь поток застрянет в ожидании завершения текущего наблюдаемого, чтобы соединить следующий.

Ответ 3

Несмотря на то, что ответы здесь хорошие, было нелегко определить разницу без примера. Итак, я создал простой пример для этого:

@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 они являются.