尽管推断出 Long,但 Collectors.maxBy(Comparator.naturalOrder()) 无法编译

Nik*_*las 4 java generics intellij-idea java-8 java-stream

我无法编译以下代码(在onlinegdb 中尝试):

List<Container<Dto>> list = Arrays.asList(
                new Container<>(new Dto("A"), 10L),
                new Container<>(new Dto("A"), 30L),
                new Container<>(new Dto("B"), 30L));

Map<String, Optional<Long>> mapWrong = list.stream()
    .collect(Collectors.groupingBy(
        c -> c.getOutput().getType(),
        Collectors.mapping(
            Container::getDifference, 
            Collectors.maxBy(Comparator.naturalOrder()))));     // DOESN'T WORK WITH THIS 
Run Code Online (Sandbox Code Playgroud)

不兼容的类型:无法推断类型变量 T,U,A,R,capture#2 of ?,T,T(参数不匹配;类 Container 中的无效方法引用方法 getDifference 不能应用于给定的类型要求:无参数找到:java.lang.Object 原因:实际和形式参数列表的长度不同)

我不知道是什么导致了编译错误。该Collectors.mapping对象映射到一个新的价值,因为Container::getDifference收益long和非常相同的类型应该被推断为Collectors.maxBy和代码应被编译。

令人惊讶的是,当我用 替换Comparator.naturalOrder()Comparator.comparingLong(l -> l),它就起作用了。

Map<String, Optional<Long>> mapCorrect = list.stream()
    .collect(Collectors.groupingBy(
        c -> c.getOutput().getType(),
        Collectors.mapping(
            Container::getDifference, 
            Collectors.maxBy(Comparator.comparingLong(l -> l)))));   // A CHANGE TO FIX IT
Run Code Online (Sandbox Code Playgroud)

使用的对象(包括 all-args 构造函数和 getter):

public class Container<T> {
    T output;
    long difference;
}
Run Code Online (Sandbox Code Playgroud)
public class Dto {
    String type;
}
Run Code Online (Sandbox Code Playgroud)

请注意,使用 OpenJDKjdk-11.0.5jdk1.8.0_212. 我使用 IntelliJ Idea 并且 IDE 没有突出显示此类错误,但是在编译时会引发该错误。

And*_*eas 7

标准 Oracle / OpenJDK 编译器(版本 8 到 14)的推理引擎无法正确跟踪正在发生的事情。

但是,Eclipse 的编译器可以,这就是其他人说他们无法重现该问题的原因。

您需要通过指定来帮助它:

Collectors.maxBy(Comparator.<Long>naturalOrder()))));     // THIS NOW WORKS
Run Code Online (Sandbox Code Playgroud)

  • 呵呵。ecj 第一次_能够_找出类型推断。 (5认同)