Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I cannot compile the following piece of code (try at 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 

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 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 -> l), then it works.

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

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

public class Container<T> {
    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.

like image 407
Nikolas Charalambidis Avatar asked Mar 02 '23 03:03

Nikolas Charalambidis


1 Answers

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.<Long>naturalOrder()))));     // THIS NOW WORKS
like image 99
Andreas Avatar answered Mar 05 '23 18:03

Andreas