`allOf` 的通用版本,导致通用列表的 `ComposableFuture`

问题描述

我正在尝试理解 CompletableFuture API,但遇到了以下问题。

allOf 本身只返回一个 CompletableFuture<void>,因此与一个名为 allResultsOf函数一个稍微更好的接口才有意义:这样的函数应该是通用的,并作为参数接收List<CompletableFuture<T>> 类型的对象并返回 CompletableFuture<List<T>>

类型的对象

我对这个函数声明的尝试是:

public static CompletableFuture<List<T>> allResultsOf(List<CompletableFuture<T>> CompletableFutures) {
                CompletableFuture<Void> allFutures = CompletableFuture
                .allOf(CompletableFutures.toArray(new CompletableFuture[CompletableFutures.size()]));
    
                CompletableFuture<List<T>> allCompletableFuture = allFutures.thenApply(
                    future -> {
                        return CompletableFutures.stream()
                            .map(CompletableFuture -> CompletableFuture.join())
                            .collect(Collectors.toList());
                });
    
                return allCompletableFuture;
            }

但是,在我的(附加的)示例代码段中,这个函数给出了这个编译错误

错误:类型不兼容:List> 无法转换为 List> CompletableFuture allCompletableFuture = allResultsOf(CompletableFutures);

我不确定这里有什么问题

示例代码(摘自here):

import java.util.*;
import java.util.stream.*;
import java.lang.*;
import java.io.*;
import java.util.concurrent.*;

// The main method must be in a class named "Main".
class Main {
    static class Test {
        private ExecutorService executor;
        public Test(ExecutorService es) {
            executor = es;
        }
        public class GreetHolder {

            private String greet;
        
            public GreetHolder(String greet) {
                this.greet = greet;
            }
        
            public String getGreet() {
                return greet;
            }
        
            public void setGreet(String greet) {
                this.greet = greet;
            }
            
            public String toString() {
                return getGreet();
            }
        }
        
        private CompletableFuture<GreetHolder> getGreeting(String lang) {
            return CompletableFuture.supplyAsync( () -> {
                try {
                    System.out.println("Task execution started for lang =" + lang);
                    Thread.sleep(200);
                    System.out.println("Task execution stopped for lang =" + lang);
                } catch (InterruptedException e) {
                    e.printstacktrace();
                }
                return new GreetHolder(getGreet(lang));
            },executor);
        }
        public String getGreet(String lang) {
            if (lang.equals("EN")) {
                return "Hello";
            } else if (lang.equals("ES")) {
                return "Hola";
            } else if (lang.equals("SN")) {
                return "Ayubovan";
            } else {
                throw new IllegalArgumentException("Invalid lang param");
            }
        }
        
        public CompletableFuture<List<Test.GreetHolder>> run() {
            List<String>  langList = Arrays.asList("EN","ES","SN"); //,"EX");

            List<CompletableFuture<Test.GreetHolder>> CompletableFutures =
            langList.stream().map(lang -> getGreeting(lang))
                //.map(CompletableFuture::join);
                .collect(Collectors.toList());
            
            // return CompletableFutures;
            
            CompletableFuture<Void> allFutures = CompletableFuture
            .allOf(CompletableFutures.toArray(new CompletableFuture[CompletableFutures.size()]));
            
            CompletableFuture<List<GreetHolder>> allCompletableFuture = allFutures.thenApply(
                future -> {
                    System.out.println(String.format("%s <- future",future));
                    return CompletableFutures.stream()
                        .map(CompletableFuture -> CompletableFuture.join())
                        .collect(Collectors.toList());
            });
            
            System.out.println(String.format("%s <- allCompletableFuture",allCompletableFuture));
            
            //return allCompletableFuture;
            
            
            CompletableFuture CompletableFuture = allCompletableFuture.thenApply(
                greets -> {
                       return greets
                            .stream()
                            .map(GreetHolder::getGreet)
                            .collect(Collectors.toList());
            });
            return CompletableFuture;
            
            
        }

        public static CompletableFuture<List<T>> allResultsOf(List<CompletableFuture<T>> CompletableFutures) {
            CompletableFuture<Void> allFutures = CompletableFuture
            .allOf(CompletableFutures.toArray(new CompletableFuture[CompletableFutures.size()]));

            CompletableFuture<List<T>> allCompletableFuture = allFutures.thenApply(
                future -> {
                    System.out.println(String.format("%s <- future",future));
                    return CompletableFutures.stream()
                        .map(CompletableFuture -> CompletableFuture.join())
                        .collect(Collectors.toList());
            });

            return allCompletableFuture;
        }

        public CompletableFuture<List<Test.GreetHolder>> run_tidier() {
            List<String>  langList = Arrays.asList("EN","EX");

            List<CompletableFuture<Test.GreetHolder>> CompletableFutures =
            langList.stream().map(lang -> getGreeting(lang))
                //.map(CompletableFuture::join);
                .collect(Collectors.toList());
            
            CompletableFuture<List<GreetHolder>> allCompletableFuture = allResultsOf(CompletableFutures);
            
            System.out.println(String.format("%s <- allCompletableFuture",allCompletableFuture));            
            
            CompletableFuture CompletableFuture = allCompletableFuture.thenApply(
                greets -> {
                       return greets
                            .stream()
                            .map(GreetHolder::getGreet)
                            .collect(Collectors.toList());
            });
            return CompletableFuture;
            
            
        }
    }
    public static void main(String[] args) throws InterruptedException,ExecutionException {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        Test t = new Test(pool);
        System.out.println(String.format("%s world!",t.getGreet("EN")));
        CompletableFuture cf = t.run();
        System.out.println(String.format("%s <- cf",cf.get()));
    }
}

解决方法

正如 Matt Timmermans 所建议的,您需要一个类型变量。

allResultsOf 更改为此编译:

public static <T> CompletableFuture<List<T>> allResultsOf(List<CompletableFuture<T>> completableFutures) {
            CompletableFuture<Void> allFutures = CompletableFuture
                    .allOf(completableFutures.toArray(new CompletableFuture[completableFutures.size()]));

            CompletableFuture<List<T>> allCompletableFuture = allFutures.thenApply(
                    future -> {
                        System.out.println(String.format("%s <- future",future));
                        return completableFutures.stream()
                                .map(completableFuture -> completableFuture.join())
                                .collect(Collectors.toList());
                    });

            return allCompletableFuture;
        }