rx java - mergemap - ¿Cuál es la diferencia entre concatMap y flatMap en RxJava?
flatmaplatest (3)
Aunque las respuestas aquí son buenas, no fue fácil detectar la diferencia sin un ejemplo. Entonces, creé un ejemplo simple para esto:
@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);
}
******** Usando flatMap () *********
1 2 3 4 5 6 7 9 8 11 13 15 10 12 14
******** Usando concatMap () *********
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Como se puede ver en la salida, los resultados para flatMap
están desordenados, mientras que para concatMap
están desordenados.
Parece que estas 2 funciones son bastante similares. Tienen la misma firma (que acepta rx.functions.Func1<? super T, ? extends Observable<? extends R>> func
), y sus diagramas de mármol tienen el mismo aspecto. No puedo pegar las fotos aquí, pero aquí hay una para concatMap , y aquí hay una para flatMap . Parece que hay alguna diferencia sutil en la descripción del Observable
resultante, donde uno producido por concatMap
contiene elementos que resultan de la concatinación de los Observables resultantes, y el producido por flatMap
contiene elementos que resultan de la primera fusión de los Observables resultantes y la emisión del resultado de esa fusion
Sin embargo, esta sutileza es totalmente incierta para mí. ¿Alguien puede dar una mejor explicación de esta diferencia e idealmente dar algunos ejemplos que ilustren esta diferencia?
Una diferencia muy importante: concatMap
espera a que se complete la observabilidad emitida y flatMap
no. flatMap
intenta iniciar el mayor número posible. Simplemente dicho: no se puede concatenar algo infinito. Solo asegúrese de que los observables que emite en concatMap
puedan completarse ; de lo contrario, todo el flujo se atascará a la espera de que se complete el observable actual para concatenar el siguiente.
Como escribiste, las dos funciones son muy similares y la diferencia sutil es cómo se crea la salida (después de que se aplica la función de mapeo).
El mapa plano utiliza el operador de fusión, mientras que concatMap utiliza el operador concat .
Como ves, la secuencia de salida de concatMap está ordenada: todos los elementos emitidos por el primer Observable se emiten antes que cualquiera de los elementos emitidos por el segundo Observable,
mientras que la secuencia de salida de flatMap se fusiona, los elementos emitidos por el observable fusionado pueden aparecer en cualquier orden, independientemente de la fuente observable de la que provienen.