簡體   English   中英

Java 8 - 在 CompleteableFuture 的 thenCompose 方法中處理元素列表

[英]Java 8 - Process list of elements in CompleteableFuture's thenCompose method

請在下面找到我的實際代碼的虛構示例。 這個例子被過度簡化來解釋我想要實現的目標。

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

}

我的getIndividualCharacters方法返回結果列表(異步)。 我使用單個結果並進一步處理它以返回另一個結果(異步)。 我想要的最終結果是List<Completeable<final result>>在這種情況下List<Completeable<Double>>我可以在CompleteablFuture.allOf中使用它

如果可能的話,我想使用 CompleteableFuture 的鏈接。 我還沒有設法找到一種方法來做到這一點,也沒有任何例子提到它。 關於如何實現這一點的任何幫助或指示都會非常有幫助。

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

問候。

我猜是這樣的?

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());

請注意,這會因為join而阻塞。

我會添加另一個答案,這可能是您的解決方案。 您可以延遲從上一個答案執行join直到您需要它。 例如通過:

 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());

但這會將結果更改為Stream ,同時 - stream 僅在調用終端操作時進行評估。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM