[英]Java 8 - Process list of elements in CompleteableFuture's thenCompose method
Please find below a made-up example of my actual code.请在下面找到我的实际代码的虚构示例。 This example has been oversimplified to explain what I am trying to achieve.
这个例子被过度简化来解释我想要实现的目标。
public class TestClass {
ForkJoinPool forkJoinPool = new ForkJoinPool(3);
@Test
public void testSample(){
List<String> testStrings = Arrays.asList("Hello", "World", "Cobra", "Eagle", "Sam");
//This doesn't compile
List<CompletableFuture<Double>> result =
testStrings.stream().map(each -> CompletableFuture.supplyAsync(() -> getIndividualCharacters(each), forkJoinPool)
.thenComposeAsync(listOfChars -> listOfChars.stream()
.map(character -> CompletableFuture.supplyAsync(() -> getDoubleString(character)))
.collect(Collectors.toList())));
}
public List<String> getIndividualCharacters(String name){
List<String> result = new ArrayList<>();
for(int i =0; i < name.length(); i++){
result.add(Character.toString(name.charAt(i)));
}
return result;
}
public Double getDoubleString(String singleCharacter){
return Math.random();
}
} }
My getIndividualCharacters
method returns a list of results (Asynchronously).我的
getIndividualCharacters
方法返回结果列表(异步)。 I use the individual result and process it further to return another result (Asynchronously).我使用单个结果并进一步处理它以返回另一个结果(异步)。 What I want as the end result is a
List<Completeable<final result>>
in this case List<Completeable<Double>>
which I can use inside CompleteablFuture.allOf
我想要的最终结果是
List<Completeable<final result>>
在这种情况下List<Completeable<Double>>
我可以在CompleteablFuture.allOf
中使用它
I want to use chaining of CompleteableFuture if possible.如果可能的话,我想使用 CompleteableFuture 的链接。 I haven't managed to find a way to do it nor any examples mention it.
我还没有设法找到一种方法来做到这一点,也没有任何例子提到它。 Any help or pointers on how to achieve this will be really helpful.
关于如何实现这一点的任何帮助或指示都会非常有帮助。
PS: I have managed to solve the problem using two separate CompleteableFuture streams, however, I want to use chaining thenCompose
PS:我已经设法使用两个独立的 CompleteableFuture 流解决了这个问题,但是,我想使用链接
thenCompose
List<String> testStrings = Arrays.asList("Hello", "World", "Cobra", "Eagle", "Sam");
List<CompletableFuture<List<String>>> firstResult = testStrings.stream()
.map(each -> CompletableFuture.supplyAsync(() -> getIndividualCharacters(each), forkJoinPool))
.collect(Collectors.toList());
CompletableFuture.allOf(firstResult.toArray(new CompletableFuture[firstResult.size()])).join();
List<CompletableFuture<Double>> secondResult = firstResult.stream()
.flatMap(res -> res.join().stream())
.map(ea -> CompletableFuture.supplyAsync(() -> getDoubleString(ea), forkJoinPool))
.collect(Collectors.toList());
List<Double> finalResult = secondResult.stream().map(res-> res.join()).collect(Collectors.toList());
System.out.println("finalResult " + finalResult);
Regards.问候。
I guess something like this?我猜是这样的?
List<CompletableFuture<Double>> result =
testStrings.stream()
.map(x -> CompletableFuture.supplyAsync(() -> getIndividualCharacters(x)))
.map(x -> x.thenApplyAsync(y -> y.stream().map(z -> CompletableFuture.supplyAsync(() -> getDoubleString(z)))))
.flatMap(CompletableFuture::join)
.collect(toList());
Just notice that this will block because of join
.请注意,这会因为
join
而阻塞。
I'll add another answer, may be this can be of a solution to you.我会添加另一个答案,这可能是您的解决方案。 You could delay the execution of
join
from the previous answer only until you would need it.您可以延迟从上一个答案执行
join
直到您需要它。 For example via:例如通过:
Stream<CompletableFuture<Double>> result =
testStrings.stream()
.map(each -> supplyAsync(() -> getIndividualCharacters(each)))
.map(x -> x.thenCompose(y -> supplyAsync(() -> y.stream().map(z -> supplyAsync(() -> getDoubleString(z))))))
.flatMap(x -> Stream.of(x).map(CompletableFuture::join))
.flatMap(Function.identity());
But this changes the result to a Stream
, at the same time - the stream is only evaluated when a terminal operation is called.但这会将结果更改为
Stream
,同时 - stream 仅在调用终端操作时进行评估。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.