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.
- Est-ce que “put” écrase les valeurs existantes?
- Manière propre de combiner plusieurs bocaux? De préférence en utilisant Ant
- Existe-t-il une fonction de substitution de chaîne générale similaire à sl4fj?
- Comment démarrer une classe de thread anonyme
- Comment obtenir le pointeur d’interface JNI (JNIEnv *) pour les appels asynchrones
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:
CompletionStage thenApply(Function super T,? extends U> 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
etStream.map
.Voir la documentation
CompletionStage
pour les règles couvrant l’achèvement exceptionnel.
CompletionStage thenCompose(Function super T,? extends CompletionStage> fn)
Renvoie une nouvelle
CompletionStage
complétée avec la même valeur que la valeurCompletionStage
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, laCompletionStage
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
etStream.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 super T,? extends U> fn
et Function super T,? extends CompletionStage> 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.