CompletableFuture | PuisApply vs thenCompose

Je ne peux pas comprendre la différence entre thenApply( ) et thenCompose() .

Ainsi, quelqu’un pourrait-il fournir un cas d’utilisation valide?

À partir des documents Java:

 thenApply(Function fn) 

Renvoie une nouvelle CompletionStage qui, lorsque cette étape se termine normalement, est exécutée avec le résultat de cette étape comme argument de la fonction fournie.

 thenCompose(Function<? super T,? extends CompletionStage> fn) 

Renvoie une nouvelle CompletionStage qui, lorsque cette étape se termine normalement, est exécutée avec cette étape comme argument de la fonction fournie.

Je comprends que le deuxième argument de thenCompose étend le CompletionStage où thenApply ne le fait pas.

Quelqu’un pourrait-il donner un exemple dans quel cas je dois utiliser thenApply et quand thenCompose ?

thenApply est utilisé si vous avez une fonction de mappage synchrone.

 CompletableFuture future = CompletableFuture.supplyAsync(() -> 1) .thenApply(x -> x+1); 

thenCompose est utilisé si vous avez une fonction de mappage asynchrone (c.-à-d. une fonction thenCompose un CompletableFuture ). Il renverra alors un futur avec le résultat directement, plutôt qu’un futur nested.

 CompletableFuture future = CompletableFuture.supplyAsync(() -> 1) .thenCompose(x -> CompletableFuture.supplyAsync(() -> x+1)); 

Les mises à jour de Java dans Java 9 vous aideront probablement à mieux comprendre:

alors appliquez

CompletionStage thenApply​(Function fn)

Renvoie une nouvelle CompletionStage qui, lorsque cette étape se termine normalement, est exécutée avec le résultat de cette étape comme argument de la fonction fournie.

Cette méthode est analogue à Optional.map et Stream.map .

Voir la documentation CompletionStage pour les règles couvrant l’achèvement exceptionnel.

alors compose

  CompletionStage thenCompose​(Function> fn) 

Renvoie une nouvelle CompletionStage complétée avec la même valeur que la valeur CompletionStage renvoyée par la fonction donnée.

Lorsque cette étape se termine normalement, la fonction donnée est appelée avec le résultat de cette étape comme argument, renvoyant une autre CompletionStage . Lorsque cette étape se termine normalement, la CompletionStage renvoyée par cette méthode est terminée avec la même valeur.

Pour assurer le progrès, la fonction fournie doit organiser l’achèvement éventuel de son résultat.

Cette méthode est analogue à Optional.flatMap et Stream.flatMap .

Voir la documentation CompletionStage pour les règles couvrant l’achèvement exceptionnel.

Je pense que la réponse publiée par @Joe C est trompeuse.

Laissez-moi essayer d’expliquer la différence entre thenApply et thenCompose avec un exemple.

Supposons que nous ayons 2 méthodes: getUserInfo(int userId) et getUserRating(UserInfo userInfo) :

 public CompletableFuture userInfo = getUserInfo(userId) public CompletableFuture getUserRating(UserInfo) 

Les deux types de retour de méthode sont CompletableFuture .

Nous voulons appeler getUserInfo() premier, et à la fin, appeler getUserRating() avec le UserInfo résultant.

À la fin de la méthode getUserInfo() , essayons tous les deux thenApply et thenCompose . La différence réside dans les types de retour:

 CompletableFuture> f = userInfo.thenApply(this::getUserRating); CompletableFuture relevanceFuture = userInfo.thenCompose(this::getUserRating); 

thenCompose() fonctionne comme le flatMap de Scala qui aplatit les futurs nesteds.

thenApply() renvoyé les futurs nesteds tels qu’ils étaient, mais thenCompose() aplati les CompletableFutures nestedes afin qu’il soit plus facile d’y enchaîner plus d’appels de méthodes.

thenApply et thenCompose est appelée sur un CompletableFuture et fait quelque chose avec son résultat en fournissant une Function . thenApply et thenCompose retournent tous les deux un CompletableFuture comme résultat, de sorte que vous puissiez enchaîner plusieurs, thenApply ou thenCompose , chacun ayant une Function faisant quelque chose pour le résultat de la dernière Function .

Cette Function doit parfois faire quelque chose de manière synchrone et retourner un résultat, auquel cas thenApply doit être utilisé.

 CompletableFuture.completedFuture(1) .thenApply((x)->x+1) // adding one to the result synchronously .thenApply((x)->System.println(x)); 

Vous pouvez également faire quelque chose d’asynchrone dans cette Function , et cette chose asynchrone que vous faites doit retourner un CompletionStage . La prochaine Function de la chaîne n’est pas intéressée par l’obtention d’une CompletionStage en entrée, mais plutôt par le résultat de cette CompletionStage . Alors, vous devriez utiliser thenCompose .

 // addOneAsync may be implemented by using another thread, or calling a remote method // CompletableFuture addOneAsync(int input); CompletableFuture.completedFuture(1) .thenCompose((x)->addOneAsync(x)) // doing something asynchronous .thenApply((x)->System.println(x)); 

En Javascript, Promise.then peut accepter une fonction, qui renvoie une valeur ou une Promise d’une valeur. En Java en raison des règles de type, les deux fonctions doivent être distinctement typées, c.-à-d. (Function fn et Function> fn . (Ou que Java doive faire une vérification de type pour faire quelque chose de spécial si vous retournez CompletionStage , mais ils a choisi l’ancien) Le résultat final étant, Promise.then est implémenté en deux parties, thenApply et thenCompose .

Vous pouvez également lire ma réponse sur thenApplyAsync si cela vous porte à confusion.