В чем разница между 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
они.