Sehr verwirrt von Java 8 Comparator-Typinferenz

Ich habe den Unterschied zwischen untersuchtCollections.sort undlist.sort, speziell in Bezug auf die Verwendung derComparator statische Methoden und ob Parametertypen in den Lambda-Ausdrücken erforderlich sind. Bevor wir anfangen, weiß ich, dass ich Methodenreferenzen verwenden könnte, z.Song::getTitle um meine Probleme zu überwinden, aber meine Abfrage hier ist nicht so sehr etwas, das ich beheben möchte, sondern etwas, auf das ich eine Antwort haben möchte, d. h. warum behandelt der Java-Compiler dies auf diese Weise.

Das sind meine Erkenntnisse. Angenommen, wir haben eineArrayList vom TypSongMit einigen hinzugefügten Songs gibt es 3 Standard-Get-Methoden:

    ArrayList<Song> playlist1 = new ArrayList<Song>();

    //add some new Song objects
    playlist.addSong( new Song("Only Girl (In The World)", 235, "Rhianna") );
    playlist.addSong( new Song("Thinking of Me", 206, "Olly Murs") );
    playlist.addSong( new Song("Raise Your Glass", 202,"P!nk") );

Hier ist ein Aufruf für beide Arten von Sortiermethoden, der problemlos funktioniert:

Collections.sort(playlist1, 
            Comparator.comparing(p1 -> p1.getTitle()));

playlist1.sort(
            Comparator.comparing(p1 -> p1.getTitle()));

Sobald ich anfange zu kettenthenComparingpassiert folgendes:

Collections.sort(playlist1,
            Comparator.comparing(p1 -> p1.getTitle())
            .thenComparing(p1 -> p1.getDuration())
            .thenComparing(p1 -> p1.getArtist())
            );

playlist1.sort(
        Comparator.comparing(p1 -> p1.getTitle())
        .thenComparing(p1 -> p1.getDuration())
        .thenComparing(p1 -> p1.getArtist())
        );

d.h. Syntaxfehler, da der Typ von nicht bekannt istp1 nicht mehr. Um dies zu beheben, füge ich den Typ hinzuSong zum ersten Parameter (zum Vergleichen):

Collections.sort(playlist1,
            Comparator.comparing((Song p1) -> p1.getTitle())
            .thenComparing(p1 -> p1.getDuration())
            .thenComparing(p1 -> p1.getArtist())
            );

playlist1.sort(
        Comparator.comparing((Song p1) -> p1.getTitle())
        .thenComparing(p1 -> p1.getDuration())
        .thenComparing(p1 -> p1.getArtist())
        );

Jetzt kommt hier der verwirrende Teil. Für Playlist1.sortd.h. die Liste, dies löst alle Kompilierungsfehler für beide folgendenthenComparing Anrufe. FürCollections.sort, es löst es für den ersten, aber nicht den letzten. Ich habe getestet, mehrere zusätzliche Anrufe hinzugefügtthenComparing und es zeigt immer einen Fehler für den letzten, es sei denn, ich setze(Song p1) für den Parameter.

Nun teste ich dies weiter mit dem Erstellen einesTreeSet und mitObjects.compare:

int x = Objects.compare(t1, t2, 
                Comparator.comparing((Song p1) -> p1.getTitle())
                .thenComparing(p1 -> p1.getDuration())
                .thenComparing(p1 -> p1.getArtist())
                );


    Set<Song> set = new TreeSet<Song>(
            Comparator.comparing((Song p1) -> p1.getTitle())
            .thenComparing(p1 -> p1.getDuration())
            .thenComparing(p1 -> p1.getArtist())
            );

Das gleiche passiert wie inTreeSet, es gibt keine übersetzungsfehler aber fürObjects.compare der letzte anruf anthenComparing zeigt einen Fehler.

Kann jemand bitte erklären, warum dies geschieht und warum es nicht erforderlich ist, es zu verwenden(Song p1) überhaupt beim einfachen Aufrufen der Vergleichsmethode (ohne weiterethenComparing Anrufe).

Eine andere Frage zum selben Thema ist, wann ich das macheTreeSet:

Set<Song> set = new TreeSet<Song>(
            Comparator.comparing(p1 -> p1.getTitle())
            .thenComparing(p1 -> p1.getDuration())
            .thenComparing(p1 -> p1.getArtist())
            );

d.h. den Typ entfernenSong Ab dem ersten Lambda-Parameter für den Aufruf der Vergleichsmethode werden Syntaxfehler unter dem Aufruf zum Vergleichen und dem ersten Aufruf von angezeigtthenComparing aber nicht zum abschließenden aufruf anthenComparing - fast das Gegenteil von dem, was oben geschah! Während für alle anderen 3 Beispiele, d.h.Objects.compare, List.sort undCollections.sort wenn ich das zuerst entferneSong Param-Typ zeigt Syntaxfehler für alle Aufrufe.

Vielen Dank im Voraus.

Bearbeitet, um einen Screenshot der Fehler aufzunehmen, die ich in Eclipse Kepler SR2 erhalten habe, die ich nun gefunden habe. Sie sind Eclipse-spezifisch, da sie beim Kompilieren mit dem Java-Compiler JDK8 in der Befehlszeile OK kompilieren.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage