Collectors.maxBy (Comparator.naturalOrder ()) no se compila aunque se infiere Long

Aug 21 2020

No puedo compilar el siguiente código (prueba en 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 

tipos incompatibles: no se puede inferir la (s) variable (s) de tipo T, U, A, R, captura # 2 de?, T, T (no coincidencia de argumentos; método de referencia de método no válido getDifference en la clase El contenedor no se puede aplicar a tipos dados requerido: no hay argumentos encontrado: java.lang.Razón del objeto: las listas de argumentos reales y formales difieren en longitud)

No tengo idea de qué causa el error de compilación. El Collectors.mappingmapea un objeto a un nuevo valor y dado que los Container::getDifferenceretornos longy el mismo tipo deben inferirse Collectors.maxByy el código debe compilarse.

Sorprendentemente, cuando reemplazo el Comparator.naturalOrder()por Comparator.comparingLong(l -> l), funciona.

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

Los objetos utilizados (incluidos el constructor all-args y los captadores):

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

Tenga en cuenta que esto se puede reproducir usando OpenJDK tanto jdk-11.0.5como jdk1.8.0_212. Utilizo IntelliJ Idea y el IDE no resalta ese error, sin embargo, lo plantea en la compilación.

Respuestas

7 Andreas Aug 21 2020 at 00:00

El motor de inferencia del compilador estándar Oracle / OpenJDK, versiones 8 a 14, no puede rastrear correctamente lo que está sucediendo.

Sin embargo, el compilador de Eclipse puede, razón por la cual otros dicen que no pueden reproducir el problema.

Necesita ayudarlo especificando:

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