Collectors.maxBy (Comparator.naturalOrder ()) не компилируется, хотя предполагается, что Long

Aug 21 2020

Я не могу скомпилировать следующий фрагмент кода (попробуйте в 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 

несовместимые типы: невозможно вывести переменные типа T, U, A, R, захват # 2 из?, T, T (несоответствие аргументов; недопустимый метод ссылки на метод getDifference в классе Container не может быть применен к заданным типам; требуются: аргументы отсутствуют найдено: java.lang. Причина объекта: фактический и формальный списки аргументов различаются по длине)

Понятия не имею, что вызывает ошибку компиляции. 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

Используемые объекты (включая конструктор all-args и геттеры):

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

Обратите внимание, что это воспроизводимо с использованием OpenJDK jdk-11.0.5и jdk1.8.0_212. Я использую IntelliJ Idea, и IDE не выделяет такую ​​ошибку, но вызывает ее при компиляции.

Ответы

7 Andreas Aug 21 2020 at 00:00

Механизм вывода стандартного компилятора Oracle / OpenJDK версий с 8 по 14 не может правильно отслеживать, что происходит.

Однако компилятор Eclipse может, поэтому другие говорят, что не могут воспроизвести проблему.

Вам нужно помочь ему, указав:

Collectors.maxBy(Comparator.<Long>naturalOrder()))));     // THIS NOW WORKS