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