Java CompletableFuture | thenApply 与 thenCompose

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43019126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:36:54  来源:igfitidea点击:

CompletableFuture | thenApply vs thenCompose

javajava-8completable-future

提问by GuyT

I can't get my head around the difference between thenApply() and thenCompose().

我无法理解thenApply() 和thenCompose().

So, could someone provide a valid use case?

那么,有人可以提供一个有效的用例吗?

From the Java docs:

来自 Java 文档:

thenApply(Function<? super T,? extends U> fn)

Returns a new CompletionStagethat, when this stage completes normally, is executed with this stage's result as the argument to the supplied function.

返回一个新的CompletionStage,当这个阶段正常完成时,将这个阶段的结果作为提供函数的参数执行。

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

Returns a new CompletionStagethat, when this stage completes normally, is executed with this stage as the argument to the supplied function.

返回一个新的CompletionStage,当这个阶段正常完成时,将这个阶段作为提供函数的参数执行。

I get that the 2nd argument of thenComposeextends the CompletionStage where thenApplydoes not.

我知道第二个参数thenCompose扩展了 CompletionStage 在哪里thenApply没有。

Could someone provide an example in which case I have to use thenApplyand when thenCompose?

有人可以提供一个示例,在哪种情况下我必须使用thenApply以及何时使用thenCompose

采纳答案by Joe C

thenApplyis used if you have a synchronous mapping function.

thenApply如果您有同步映射功能,则使用。

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

thenComposeis used if you have an asynchronous mapping function (i.e. one that returns a CompletableFuture). It will then return a future with the result directly, rather than a nested future.

thenCompose如果您有异步映射函数(即返回 a 的函数CompletableFuture),则使用它。然后它将直接返回带有结果的未来,而不是嵌套的未来。

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

回答by Didier L

The updated Javadocs in Java 9 will probably help understand it better:

Java 9 中更新的 Javadocs 可能有助于更好地理解它:

thenApply

然后申请

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

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

Returns a new CompletionStagethat, when this stage completes normally, is executed with this stage's result as the argument to the supplied function.

This method is analogous to Optional.mapand Stream.map.

See the CompletionStagedocumentation for rules covering exceptional completion.

返回一个新的CompletionStage,当这个阶段正常完成时,将这个阶段的结果作为提供函数的参数执行。

这种方法类似于Optional.mapStream.map

有关CompletionStage涵盖异常完成的规则​​,请参阅文档。

thenCompose

然后撰写

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

Returns a new CompletionStagethat is completed with the same value as the CompletionStagereturned by the given function.

When this stage completes normally, the given function is invoked with this stage's result as the argument, returning another CompletionStage. When that stage completes normally, the CompletionStagereturned by this method is completed with the same value.

To ensure progress, the supplied function must arrange eventual completion of its result.

This method is analogous to Optional.flatMapand Stream.flatMap.

See the CompletionStagedocumentation for rules covering exceptional completion.

返回一个CompletionStageCompletionStage给定函数返回的值相同的新值。

当此阶段正常完成时,将使用此阶段的结果作为参数调用给定函数,并返回另一个 CompletionStage. 当该阶段正常完成时, CompletionStage此方法返回的值以相同的值完成。

为确保进度,提供的函数必须安排其结果的最终完成。

这种方法类似于Optional.flatMapStream.flatMap

有关CompletionStage涵盖异常完成的规则​​,请参阅文档。

回答by Dorjee

I think the answered posted by @Joe C is misleading.

我认为@Joe C 发布的回答具有误导性。

Let me try to explain the difference between thenApplyand thenComposewith an example.

让我试着解释之间的差别thenApply,并thenCompose用一个例子。

Let's suppose that we have 2 methods: getUserInfo(int userId)and getUserRating(UserInfo userInfo):

假设我们有 2 个方法:getUserInfo(int userId)getUserRating(UserInfo userInfo)

public CompletableFuture<UserInfo> getUserInfo(userId)

public CompletableFuture<UserRating> getUserRating(UserInfo)

Both method return types are CompletableFuture.

两种方法的返回类型都是CompletableFuture.

We want to call getUserInfo()first, and on its completion, call getUserRating()with the resulting UserInfo.

我们想先调用getUserInfo(),并在调用完成时getUserRating()使用结果调用UserInfo

On the completion of getUserInfo()method, let's try both thenApplyand thenCompose. The difference is in the return types:

getUserInfo()方法完成时,让我们同时尝试thenApplythenCompose。区别在于返回类型:

CompletableFuture<CompletableFuture<UserRating>> f =
    userInfo.thenApply(this::getUserRating);

CompletableFuture<UserRating> relevanceFuture =
    userInfo.thenCompose(this::getUserRating);

thenCompose()works like Scala's flatMapwhich flattens nested futures.

thenCompose()就像Scala 的一样flatMap,它可以将嵌套的期货展平。

thenApply()returned the nested futures as they were, but thenCompose()flattened the nested CompletableFuturesso that it is easier to chain more method calls to it.

thenApply()原样返回嵌套的期货,但将嵌套的期货展thenCompose()平,CompletableFutures以便更容易地将更多的方法调用链接到它。

回答by 1283822

thenApplyand thenComposeare methods of CompletableFuture. Use them when you intend to do something to CompleteableFuture's result with a Function.

thenApplythenCompose是的方法CompletableFuture。当你打算做些什么来使用他们CompleteableFuture的一个结果Function

thenApplyand thenComposeboth return a CompletableFutureas their own result. You can chain multiple thenApplyor thenComposetogether. Supply a Functionto each call, whose result will be the input to the next Function.

thenApply并且thenCompose都返回 aCompletableFuture作为他们自己的结果。您可以将多个链接thenApply或链接thenCompose在一起。Function为每个调用提供 a ,其结果将是下一个 的输入Function

The Functionyou supplied sometimes needs to do something synchronously. The return type of your Functionshould be a non-Futuretype. In this case you should use thenApply.

Function你提供的,有时需要同步做一些事情。您的返回类型Function应该是非Future类型。在这种情况下,您应该使用thenApply.

CompletableFuture.completedFuture(1)
    .thenApply((x)->x+1) // adding one to the result synchronously, returns int
    .thenApply((y)->System.println(y)); // value of y is 1 + 1 = 2

Other times you may want to do asynchronous processing in this Function. In that case you should use thenCompose. The return type of your Functionshould be a CompletionStage. The next Functionin the chain will get the result of that CompletionStageas input, thus unwrapping the CompletionStage.

其他时候你可能想在这个中做异步处理Function。在这种情况下,您应该使用thenCompose. 您的返回类型Function应该是CompletionStage. Function链中的下一个将得到它的结果CompletionStage作为输入,从而解开CompletionStage.

// addOneAsync may be implemented by using another thread, or calling a remote method
abstract CompletableFuture<Integer> addOneAsync(int input);

CompletableFuture.completedFuture(1)
    .thenCompose((x)->addOneAsync(x)) // doing something asynchronous, returns CompletableFuture<Integer>
    .thenApply((y)->System.println(y)); // y is an Integer, the result of CompletableFuture<Integer> above

This is a similar idea to Javascript's Promise. Promise.thencan accept a function that either returns a value or a Promiseof a value. The reason why these two methods have different names in Java is due to generic erasure. Function<? super T,? extends U> fnand Function<? super T,? extends CompletionStage<U>> fnare considered the same Runtime type - Function. Thus thenApplyand thenComposehave to be distinctly named, or Java compiler would complain about identical method signatures. The end result being, Javascript's Promise.thenis implemented in two parts - thenApplyand thenCompose- in Java.

这与 Javascript 的Promise. Promise.then可以接受返回值或Promise值的函数。这两种方法在 Java 中具有不同名称的原因是泛型擦除Function<? super T,? extends U> fn并且Function<? super T,? extends CompletionStage<U>> fn被认为是相同的运行时类型 - Function。因此thenApplythenCompose必须明确命名,否则 Java 编译器会抱怨相同的方法签名。最终的结果是,Javascript 的Promise.then实现分为两部分 -thenApplythenCompose- 在 Java 中。

You can read my other answerif you are also confused about a related function thenApplyAsync.

如果您也对相关功能感到困惑,可以阅读我的其他答案thenApplyAsync