Collectors.maxBy (Comparator.naturalOrder ()) tidak dapat dikompilasi meskipun Long disimpulkan

Aug 21 2020

Saya tidak dapat mengkompilasi potongan kode berikut (coba di 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 

tipe yang tidak kompatibel: tidak dapat menyimpulkan tipe-variabel T, U, A, R, capture # 2 dari?, T, T (argumen tidak cocok; metode referensi metode tidak valid getDifference di kelas Kontainer tidak dapat diterapkan ke tipe yang diberikan diperlukan: tidak ada argumen ditemukan: java.lang.Object alasan: daftar argumen aktual dan formal berbeda panjangnya)

Saya tidak tahu apa yang menyebabkan kesalahan kompilasi. The Collectors.mappingpeta objek ke nilai baru dan sejak Container::getDifferencekembali longdan jenis yang sama harus disimpulkan ke dalam Collectors.maxBydan kode harus mendapatkan dikompilasi.

Anehnya, ketika saya mengganti Comparator.naturalOrder()dengan Comparator.comparingLong(l -> l), maka itu berhasil.

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

Objek yang digunakan (termasuk konstruktor dan getter all-args):

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

Catatan ini dapat direproduksi menggunakan OpenJDK baik jdk-11.0.5dan jdk1.8.0_212. Saya menggunakan IntelliJ Idea dan IDE tidak menyoroti kesalahan tersebut, namun memunculkannya saat kompilasi.

Jawaban

7 Andreas Aug 21 2020 at 00:00

Mesin inferensi dari kompiler Oracle / OpenJDK standar, versi 8 hingga 14, tidak dapat melacak dengan benar apa yang sedang terjadi.

Namun, kompilator Eclipse bisa, itulah sebabnya orang lain mengatakan mereka tidak dapat mereproduksi masalah tersebut.

Anda perlu membantunya dengan menentukan:

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