java.util.function.BiConsumer<R,R>) 不适用(无法推断类型变量 R

java.util.function.BiConsumer<R,R>) is not applicable (cannot infer type-variable(s) R

我尝试编写一些流代码,将 report 个对象减少为一个 report 个对象。

我有这个 java 代码 获取字符串(请求)获取 http 响应 --> 将其传递给与保存在内存中的旧响应进行比较。

我想收集 n compare resultsResult 个对象

最终我想将 m report 个对象聚合为一个对象。

我有这个代码

请求的类型为 string

report

类型的总报表

compare result

类型的比较 2

和:

        Report report = requestsList
                .parallelStream()
                .map(request ->
                                getResponse(request, e2EResultLongBL, e2EResultLongFresh)
                )
                .map(response -> compareToBl(response, e2EResultLongBL))
                .collect(null,
                        (sumReport, compare2) ->
                        {
                            if (sumReport == null)
                            {
                                sumReport = new Report();
                            }
                            sumReport.add(compare2);
                            return  sumReport;
                        },
                        (report1, report2) ->
                        {
                            Report report3 = new Report();
                            report3.add(report2);
                            return report3;
                        });

为什么会出现这个错误?

Error:(174, 21) java: no suitable method found for collect(<nulltype>,(sumReport[...]rt; },(report1,r[...]t3; })
    method java.util.stream.Stream.<R>collect(java.util.function.Supplier<R>,java.util.function.BiConsumer<R,? super com.waze.routing.automation.dataModel.ComparisonResult>,java.util.function.BiConsumer<R,R>) is not applicable
      (cannot infer type-variable(s) R
        (argument mismatch; unexpected return value))
    method java.util.stream.Stream.<R,A>collect(java.util.stream.Collector<? super com.waze.routing.automation.dataModel.ComparisonResult,A,R>) is not applicable
      (cannot infer type-variable(s) R,A
        (actual and formal argument lists differ in length))

最好的猜测——你没有提供太多细节——我希望你需要的只是 collect(Report::new, Report::add, Report::add),这或多或少说:为累加器创建新的报告,调用 Report.add 将元素添加到 Report,并调用 Report.add(可能是不同的重载)将第二个 Report 组合到第一个 Report).

有趣的是,如果您改为调用 reduce(),它会编译。

通常,第一个参数可以为类型推断提供一些约束;不幸的是,您在这里使用 null。仅通过查看方法调用,无法判断 R 可以是什么。幸运的是,方法调用是在赋值上下文中,因此 R 可以推断为 Report.

唯一的问题是 lambda 体内的 value-return 语句,而函数类型应该是 void-return。由于 return 类型不同,它适用于 reduce()

编译器在 lambda 主体中使用 return 语句来约束 lambda 的类型,这在例如重载决议中很有用

    ExecutorService es= ...;
    es.submit( ()->{ return new Object(); } );      // submit(Callable)
    es.submit( ()->{        new Object(); } );      // submit(Runnable)

处理 void 是一件棘手的事情,例如此代码不编译,这是合理的

    Executor ex = null;
    ex.execute( ()->{ return new Object(); } ); // error, ()->void is expected

不过这两种形式确实编译通过,也是合理有用的

    ex.execute(()->new Object());
    ex.execute(Object::new);

我认为这是由于 JDK 错误造成的:在某些情况下,JDK 1.8.0_25 无法正确重新调整 lambda。

一个类似的线程得出相同的结论。

我建议您将您的 sdk 版本 (java -version) 至少更新到 1.8。0_45