Collectors.maxBy(Comparator.naturalOrder()) doesn't compile although Long is inferred

huangapple go评论79阅读模式
英文:

Collectors.maxBy(Comparator.naturalOrder()) doesn't compile although Long is inferred

问题

以下是您提供的代码的翻译部分:

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()))));     // 无法与此代码一起工作
Map<String, Optional<Long>> mapCorrect = list.stream()
    .collect(Collectors.groupingBy(
        c -> c.getOutput().getType(),
        Collectors.mapping(
            Container::getDifference, 
            Collectors.maxBy(Comparator.comparingLong(l -> l)))));   // 修复此处以解决问题

对象的定义(包括全参数构造函数和获取方法):

public class Container<T> {
    T output;
    long difference;
}
public class Dto {
    String type;
}

注意,这个问题可以在 OpenJDK 的 jdk-11.0.5jdk1.8.0_212 版本中重现。我使用 IntelliJ Idea,这个IDE不会突出显示这种错误,但会在编译时引发错误。

英文:

I cannot compile the following piece of code (try at onlinegdb):

List&lt;Container&lt;Dto&gt;&gt; list = Arrays.asList(
                new Container&lt;&gt;(new Dto(&quot;A&quot;), 10L),
                new Container&lt;&gt;(new Dto(&quot;A&quot;), 30L),
                new Container&lt;&gt;(new Dto(&quot;B&quot;), 30L));

Map&lt;String, Optional&lt;Long&gt;&gt; mapWrong = list.stream()
    .collect(Collectors.groupingBy(
        c -&gt; c.getOutput().getType(),
        Collectors.mapping(
            Container::getDifference, 
            Collectors.maxBy(Comparator.naturalOrder()))));     // DOESN&#39;T WORK WITH THIS 

> incompatible types: cannot infer type-variable(s) T,U,A,R,capture#2 of ?,T,T
(argument mismatch; invalid method reference
method getDifference in class Container<T> cannot be applied to given types
required: no arguments
found: java.lang.Object
reason: actual and formal argument lists differ in length)

I have no idea what causes the compilation error. The Collectors.mapping maps an object to a new value and since Container::getDifference returns long and the very same type should be inferred into Collectors.maxBy and the code should get compiled.

Surprisingly, when I replace the Comparator.naturalOrder() with Comparator.comparingLong(l -&gt; l), then it works.

Map&lt;String, Optional&lt;Long&gt;&gt; mapCorrect = list.stream()
    .collect(Collectors.groupingBy(
        c -&gt; c.getOutput().getType(),
        Collectors.mapping(
            Container::getDifference, 
            Collectors.maxBy(Comparator.comparingLong(l -&gt; l)))));   // A CHANGE TO FIX IT

The objects used (including all-args constructor and getters):

public class Container&lt;T&gt; {
    T output;
    long difference;
}
public class Dto {
    String type;
}

Note this is reproducible using OpenJDK both jdk-11.0.5 and jdk1.8.0_212. I use IntelliJ Idea and the IDE doesn't highligh such error, however raises it on compilation.

答案1

得分: 7

标准的Oracle / OpenJDK编译器版本8至14的推理引擎无法正确跟踪发生的情况。

然而,Eclipse的编译器可以,这就是为什么其他人说他们无法重现这个问题。

您需要通过指定以下方式来帮助它:

Collectors.maxBy(Comparator.<Long>naturalOrder()))));     // 现在可以工作
英文:

The inference engine of the standard Oracle / OpenJDK compiler, versions 8 to 14, cannot correctly track what is going on.

However, Eclipse's compiler can, which is why others say they cannot reproduce the issue.

You need to help it along by specifying:

Collectors.maxBy(Comparator.&lt;Long&gt;naturalOrder()))));     // THIS NOW WORKS

huangapple
  • 本文由 发表于 2020年8月21日 00:37:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63509530.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定