web-dev-qa-db-fra.com

Quelle est la différence entre concatMap et flatMap dans RxJava

Il semble que ces 2 fonctions soient assez similaires. Ils ont la même signature (acceptant rx.functions.Func1<? super T, ? extends Observable<? extends R>> func), et leurs diagrammes en marbre sont identiques. Impossible de coller les photos ici, mais en voici une pour concatMap , et en voici une pour flatMap . Il semble y avoir une différence subtile dans la description de Observable résultant, où celui produit par concatMap contient des éléments résultant de la concaténation des observables résultants, et celui produit par flatMap contient les éléments qui résultent de la fusion des Observables résultants et de l'émission du résultat de cette fusion.

Cependant, cette subtilité n'est pas du tout claire pour moi. Quelqu'un peut-il donner une meilleure explication de cette différence, et idéalement donner quelques exemples illustrant cette différence.

41
Haspemulator


Comme vous l'avez écrit, les deux fonctions sont très similaires et la différence subtile réside dans la façon dont la sortie est créée (après l'application de la fonction de mappage).

La carte plate utilise opérateur de fusion tandis que concatMap utilise opérateur de concat .

Comme vous le voyez, la séquence de sortie concatMap est ordonnée - tous les éléments émis par le premier observable étant émis avant l'un des éléments émis par le deuxième observable,
pendant la fusion de la séquence de sortie flatMap - les éléments émis par l'Observable fusionné peuvent apparaître dans n'importe quel ordre, quelle que soit la source d'Observable dont ils sont issus.

55
Marek Hawrylczak

Une différence très importante: le concatMap attend la fin du courant observé émis et flatMap ne le fait pas. flatMap essaie de démarrer autant que possible. Dit simplement - vous ne pouvez pas enchaîner quelque chose d'infini. Assurez-vous simplement que les observables que vous émettez dans concatMap peuvent se terminer, sinon le flux entier restera bloqué en attendant que l'observable actuel se termine pour concaténer le suivant.

14
WindRider

Même si les réponses ici sont bonnes, il n'a pas été facile de distinguer la différence sans un exemple. J'ai donc créé un exemple simple pour cela:

@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);
}

******** Utilisation de flatMap () *********

1 2 3 4 5 6 7 9 8 11 13 15 10 12 14

******** Utilisation de concatMap () *********

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Comme on peut le voir sur la sortie, les résultats pour flatMap ne sont pas ordonnés tandis que pour concatMap ils le sont.

14
Anatolii