【问题标题】:What is defaulting this Collectors.toList to expect a List of Object?什么是默认此 Collectors.toList 期望对象列表?
【发布时间】:2017-12-12 18:33:27
【问题描述】:

我们正在使用 Java 中的 @Async 注释和 CompletableFutures 对一些调用进行异步处理。我们有许多 Pojo,我们在异步调用中为其创建对象,但是当尝试将结果收集到列表时,Eclipse 希望我将 Pojo 列表更改为对象列表,而我不是了解是否是 CompletableFuture 默认来自流的响应。

List<Pojo1> crudResponse = null;
List<Pojo1> listOfIterations =  new ArrayList<>();

//populates object with multiple entries in list
listOfIteration = populateIterationObject(param);

crudResponse = listOfIterations.stream()
    .map(str -> CompletableFuture.supplyAsync(() -> {
        try {
            return async.hitCrud(str);
            }catch(RequestProcessingException e){
                log.error(e);
            }
            return function;
        }))
        .map(CompletableFuture::join)
        .collect(Collectors.toList());
        }

//async class
    public CompletableFuture<Pojo1> hitCrud(Pojo1 iteration) throws RequestProcessingException {

        try {
            String response;
            Pojo1 pojoResponse;
            response = connectToCrud(iteration);

            if(response != null) {
                pojoResponse.add(response);
            }                       
        }catch(Exception ex){
            log.error(ex);
        }
        return CompletableFuture.completedFuture(pojoResponse);
    }

我点击了返回 Pojo1 对象的方法,但是当我尝试使用 Collectors.toList() 创建一个列表时,它期望我有一个可以使用的 &lt;Object&gt; 列表,但需要更多编码拉出并投射我从异步调用中得到的每个响应。

这是默认为 Object 的 CompletableFuture 吗?如果是这样,是否可以将其默认为 Pojo1 的类型?

编辑: 我在 IDE 中看到的错误:

Type mismatch: cannot convert from List<Object> to List<Pojo1>

【问题讨论】:

  • 不,是编辑器弄糊涂了,无法推断出类型。他们有时会这样做。
  • 实际上,您似乎确实有一些类型安全问题,但由于您的示例不完整,因此很难确定。我已经能够弥补大部分缺失的位,但function 的类型是什么?

标签: java asynchronous completable-future


【解决方案1】:

Java 推断出与您想要的不同的类型绑定,因为您的代码错误。给定

//async class
public CompletableFuture<Pojo1> hitCrud(Pojo1 iteration) // ...

List<Pojo1> crudResponse = null;
List<Pojo1> listOfIterations =  new ArrayList<>();

...,我们来分析一下这个流表达式:

crudResponse = listOfIterations.stream()
    .map(str -> CompletableFuture.supplyAsync(() -> {
        try {
            return async.hitCrud(str);
            }catch(RequestProcessingException e){
                log.error(e);
            }
            return function;
        }))
        .map(CompletableFuture::join)
        .collect(Collectors.toList());
  • listOfIterations.stream() 产生 Stream&lt;Pojo1&gt;
  • 第一个 map() 方法调用的类型参数必须从参数中推断出来,作为外部 lambda 的返回类型。
  • 外部 lambda 的返回类型本身必须从 CompletableFuture.supplyAsync() 调用的返回类型中推断出来,...
  • 它本身就是内部 lambda 的返回类型。那么返回类型是什么?
    • 嗯,内部的lambda可以返回调用async.hitCrud(str)的结果,一个CompletableFuture&lt;Pojo1&gt;
    • 或者它可以返回function,无论它的类型是什么。
    • 推断的类型将是这两种类型中最近的共同祖先,很可能是CompletableFuture&lt;Pojo1&gt;Object。鉴于错误信息,大概是Object
  • 所以你已经映射到Stream&lt;CompletableFuture&lt;Object&gt;&gt;,因此下一个映射产生Stream&lt;Object&gt;
  • 将其收集到列表中会给您一个List&lt;Object&gt;,而不是List&lt;Pojo1&gt;

这不仅仅是一个外观问题:该列表可能确实包含不是Pojo1s 的对象。

要看到这一点,请考虑如果function 具有CompletableFuture&lt;Pojo1&gt; 类型,分析将如何变化,hitCrud() 的返回值也是如此。那么内部 lambda 的返回类型将是 CompletableFuture&lt;Pojo1&gt;,但这会使 outer lambda 的返回类型为 CompletableFuture&lt;CompletableFuture&lt;Pojo1&gt;&gt;,最终给你一个 List&lt;CompletableFuture&lt;Pojo1&gt;&gt;,这仍然不是你的想。如果这确实是您的情况,那么您可以通过消除外部 lambda 来解决问题,以便您仅使用内部 lambda 映射 str

crudResponse = listOfIterations.stream()
    .map(str -> {
            try {
                return async.hitCrud(str);
            } catch(RequestProcessingException e) {
                log.error(e);
            }
            return function;
        })
        .map(CompletableFuture::join)
        .collect(Collectors.toList());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多