ロングが推測されますが、Collectors.maxBy(Comparator.naturalOrder())はコンパイルされません

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、capture#2 of?、T、Tを推測できません(引数の不一致;クラスContainerの無効なメソッド参照メソッドgetDifferenceは、必要な特定のタイプに適用できません:引数なし見つかった:java.lang.Object理由:実際の引数リストと正式な引数リストの長さが異なります)

コンパイルエラーの原因がわかりません。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

使用されるオブジェクト(すべての引数のコンストラクターとゲッターを含む):

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

これは、OpenJDKとの両方jdk-11.0.5を使用して再現可能であることに注意してくださいjdk1.8.0_212。私はIntelliJIdeaを使用しており、IDEはそのようなエラーを強調しませんが、コンパイル時にエラーを発生させます。

回答

7 Andreas Aug 21 2020 at 00:00

標準のOracle / OpenJDKコンパイラバージョン8〜14の推論エンジンは、何が起こっているかを正しく追跡できません。

ただし、Eclipseのコンパイラは可能です。そのため、他の人は問題を再現できないと言っています。

次のように指定して、それを支援する必要があります。

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