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

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

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

3 ответов



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

плоская карта использует слияние оператора пока concatMap использует оператор функция concat.

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


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


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

@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 они.