2

我正在尝试创建多个List 类型的CompletionStage,例如。CompletionStage<List<Car>>. 最后,我想在一个CompletionStage中将所有类型的响应合并<List<Car>>到一个 List 中。

CompletionStage<List<Car>> completionStageOne= carClientOne.getCarList();
CompletionStage<List<Car>> completionStageTwo= carClientTwo.getCarList();
CompletionStage<List<Car>> completionStageThree= carClientThree.getCarList();

所以在这里,假设我有 3 种不同的服务,它们会给我不同的汽车列表作为响应形式CompletionStage<List<Car>>

现在我正在尝试将它们结合起来并创建一个通用的汽车列表,这里我遇到了问题。我正在使用下面的代码来组合结果

CompletionStage<List<Car>> completionStageOneTwo = completionStageOne
.thenCombine(completionStageTwo,(x, y) -> Stream.concat(x.stream(), y.stream()).collect(Collectors.toList()));

//above will work but if I add the third one then it will not. 

CompletionStage<List<Car>> completionStageFinal = completionStageOneTwo
.thenCombine(completionStageThree,(x, y) -> Stream.concat(x.stream(), y.stream()).collect(Collectors.toList())); 

最后我在做

List<Car> finalList = completionStageFinal.toCompletableFuture().get();

那么我做错了什么?我怎样才能将这三个结合起来?我在阻止什么吗?

注意:我已经从 Holger 检查了这个答案,但无法弄清楚如何在那里使用 concat 。

4

2 回答 2

4

让我给你看一个例子。我将展示如何使用CompletableFuture.AllOf(...)which 允许等待所有的期货。

    // create promises to get cars
    CompletableFuture<List<String>> cars1 = CompletableFuture.completedFuture(Arrays.asList("BMW", "Alfa"));
    CompletableFuture<List<String>> cars2 = CompletableFuture.completedFuture(Collections.singletonList("WV"));
    CompletableFuture<List<String>> cars3 = CompletableFuture.completedFuture(Collections.singletonList("FIAT"));

    // collect promises just for convenience
    List<CompletableFuture<List<String>>> allFutures = Arrays.asList(cars1, cars2, cars3);

    // wait until all cars will be obtained
    CompletableFuture<List<String>> listCompletableFuture =
            CompletableFuture.allOf(cars1, cars2, cars3)
            .thenApply(avoid -> allFutures  //start to collect them
                    .stream()
                    .flatMap(f -> f.join().stream()) //get List from feature. Here these cars has been obtained, therefore non blocking
                    .collect(Collectors.toList())
    );

    // there are here
    listCompletableFuture.join().forEach(System.out::println);

输出:

BMW
Alfa
WV
FIAT
于 2018-08-28T21:22:01.287 回答
2

我实际上遇到了同样的问题,并举了一个例子来说明我如何使用多个可完成的期货来构造一个对象。

https://github.com/te21wals/CompletableFuturesDemo

这比需要的“进取心”多一点,但是您应该能够理解这个想法。

public static void main (String[] args){
    CompletableFuture<ClassA> classAfuture = futureProvider.retrieveClassA();
    CompletableFuture<ClassB> classBfuture = futureProvider.retrieveClassB();
    CompletableFuture<ClassC> classCfuture = futureProvider.retrieveClassC();

    System.out.println("starting completable futures ...");
    long startTime = System.nanoTime();

    ABCData ABCData = CompletableFuture.allOf(classAfuture, classBfuture, classCfuture)
            .thenApply(ignored ->
                    combineFunction.combind(
                            classAfuture.join(),
                            classBfuture.join(),
                            classCfuture.join())
            ).join();

    long endTime = System.nanoTime();
    long duration = (endTime - startTime);
    System.out.println("completable futures are complete...");
    System.out.println("duration:\t" + Duration.ofNanos(duration).toString());
    System.out.println("result:\t" + ABCData);
} 

您获得的一个很好的额外好处是总请求只需要最长的单个请求的时间。

于 2018-09-12T19:53:04.353 回答