RxJava: merge () cambia el orden de los elementos emitidos?

Francesco:

Mira estas 2 pequeñas pruebas:

@Test
public void test1() {
    Observable.range(1, 10)
        .groupBy(v -> v % 2 == 0)
        .flatMap(group -> {
            if (group.getKey()) {
                return group;
            }
            return group;
        })
        .subscribe(System.out::println);
}

@Test
public void test2() {
    Observable.range(1, 10)
        .groupBy(v -> v % 2 == 0)
        .toMap(g -> g.getKey())
        .flatMapObservable(m -> Observable.merge(
            m.get(true),
            m.get(false)))
        .subscribe(System.out::println);
}

Yo estaba esperando tanto para devolver una lista de números en el mismo orden, por lo que:

1 2 3 4 5 6 7 8 9 10

Pero el ejemplo el segundo reenvíos

2 4 6 8 10 1 3 5 7 9

en lugar.

Parece que en el segundo ejemplo, el mergeestá haciendo un concatcambio, de hecho, si lo cambio a una concat, el resultado es el mismo.

¿Qué me estoy perdiendo?

Gracias.

TmTron:

Básicamente flatMapy mergeno garantizan el orden de los artículos emitidos.

De flatMap doc:

Tenga en cuenta que FlatMap fusiona las emisiones de estos observables, de modo que puedan intercalar.

De fusión doc:

De mezcla puede intercalar los artículos emitidos por los observables fusionadas (un operador similares, de concatenación, hace artículos no intercalación, pero emite todos los elementos de cada fuente observables a su vez antes de comenzar a emitir los artículos en la siguiente fuente observable).

Citar de este SO respuesta :

En su caso, con un solo elemento, corrientes estáticas, no está haciendo una diferencia real (pero en teoría, podría fusión palabras de salida en orden aleatorio y aún así ser válida de acuerdo a las especificaciones)

Si necesita un uso para garantizar concat*su lugar.

primer ejemplo

Funciona así:

  • cuando 1se emite el groupByoperador creará una GroupedObservablecon llavefalse
    • flatMap dará salida a los artículos de este observable - que es en la actualidad sólo 1
  • cuando 2se emite el groupByoperador creará una GroupedObservablecon llavetrue
    • flatMapAhora también tendrá salida los artículos de este segundo GroupedObservable- que se encuentra actualmente2
  • cuando 3se emite el groupByoperador de la añadirá a la ya existente GroupedObservablecon llave falsey la flatMapvoluntad saldrá este elemento de inmediato
  • cuando 4se emite el groupByoperador de la añadirá a la ya existente GroupedObservablecon llave truey la flatMapvoluntad saldrá este elemento de inmediato
  • etcétera

Puede ayudarle a añadir un poco más de registro:

    Observable.range(1, 10)
            .groupBy(v -> v % 2 == 0)
            .doOnNext(group -> System.out.println("key: " + group.getKey()))
            .flatMap(group -> {
                if (group.getKey()) {
                    return group;
                }
                return group;
            })
            .subscribe(System.out::println);

A continuación, la salida es:

key: false
1
key: true
2
3
...

El segundo ejemplo

Esto es muy diferente, porque toMapse bloqueará hasta que se complete aguas arriba:

  • cuando 1se emite el groupByoperador creará una GroupedObservablecon llavefalse
    • toMapagregará este GroupedObservableal mapa interno y utiliza la clave false(la misma tecla que la GroupedObservabletiene)
  • cuando 2se emite el groupByoperador creará una GroupedObservablecon llavetrue
    • toMapagregará este GroupedObservableal mapa interno y utiliza la clave true(la misma tecla que la GroupedObservabletiene) - por lo que ahora el mapa tiene 2GroupedObservables
  • los números siguientes se añaden a los correspondientes GroupedObservablesy cuando finaliza el origen, el toMapoperador está hecho y pasará el mapa para el siguiente operador
  • en el flatMapObservableque utilizar el mapa para crear un nuevo observable donde se añade por primera vez los elementos clave pares (= true) y luego los elementos impares (clave = false)

También en este caso se podría añadir un poco más de registro:

    Observable.range(1, 10)
            .groupBy(v -> v % 2 == 0)
            .doOnNext(group -> System.out.println("key: " + group.getKey()))
            .toMap(g -> g.getKey())
            .doOnSuccess(map -> System.out.println("map: " + map.size()))
            .flatMapObservable(m -> Observable.merge(
                    m.get(true),
                    m.get(false)
            ))
            .subscribe(System.out::println);

A continuación, la salida es:

key: false
key: true
map: 2
2
4
6
8
10
1
3
5
7
9

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=213648&siteId=1
Recomendado
Clasificación