Sehr verwirrt von Java 8 Komparator-Typ-Inferenz

Habe ich den Unterschied zwischen Collections.sort und list.sort, insbesondere in Bezug auf die Verwendung der Comparator statische Methoden und ob param Typen erforderlich sind in der lambda-Ausdrücke. Bevor wir beginnen, ich weiß, dass ich verwenden könnte, Methode, Referenzen, z.B. Song::getTitle zu überwinden, meine Probleme, aber meine Anfrage hier ist nicht so sehr etwas, was ich beheben wollen, sondern etwas, was ich wollen eine Antwort, also warum ist der Java-compiler die Handhabung es auf diese Weise.

Diese sind bei meinem Befund. Nehmen wir an, wir haben eine ArrayList Typ Song mit einigen songs Hinzugefügt, es gibt 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 an beide Typen der sort-Methode, die funktioniert, kein problem:

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

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

Sobald ich an die Kette thenComparing ist, geschieht 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. syntax-Fehler, weil Sie nicht wissen, die Art der p1 mehr. So, dies zu beheben, ich geben Sie Song auf den ersten parameter (der Vergleich):

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 der VERWIRRENDE Teil. Für playlist1.sort, D. H. die Liste, diese lösen alle Kompilierungsfehler, für die beiden folgenden thenComparing Anrufe. Jedoch, für Collections.sort, es löst es für das erste, aber nicht der Letzte. Getestet habe ich Hinzugefügt einige zusätzliche Aufrufe thenComparing und es zeigt immer einen Fehler an, für den letzten, wenn ich (Song p1) für die parameter.

Nun ging ich auf um zu testen, dies weiter mit der Erstellung eines TreeSet und mit Objects.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 in, für die TreeSet gibt es keine Kompilierungsfehler aber für Objects.compare dem letzten Aufruf thenComparing erscheint eine Fehlermeldung.

Kann mir jemand bitte erklären, warum das passiert ist und auch warum gibt es keine Notwendigkeit zu verwenden (Song p1) an alle, wenn Sie einfach den Aufruf der Vergleichs-Methode (ohne weitere thenComparing Anrufe).

Einer anderen Abfrage auf das gleiche Thema ist, wenn ich dies tun, um die TreeSet:

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

D. H. entfernen der Typ Song von der ersten lambda-parameter für die Vergleich-Methode aufrufen, zeigt es syntax-Fehler unter den Aufruf zu vergleichen und den ersten Anruf zu thenComparing aber nicht der Letzte Aufruf thenComparing - fast das Gegenteil von dem, was passiert war oben! In der Erwägung, dass, für alle anderen 3 Beispiele, d.h. mit Objects.compare, List.sort und Collections.sort wenn ich die zuerst entfernen Song param-Typ zeigt es syntax-Fehler für alle Anrufe.

Vielen Dank im Voraus.

Bearbeitet gehören screenshot von Fehler, die ich erhalte in Eclipse Kepler SR2, die ich jetzt haben, da sind Eclipse-spezifisch, weil bei der Kompilierung mit dem JDK8 java-compiler auf der Kommandozeile kompiliert OK.

Sehr verwirrt von Java 8 Komparator-Typ-Inferenz

Es wäre hilfreich, wenn Sie uns in Ihrer Anfrage an alle die Kompilierung Fehlermeldungen, die Sie bekommen in der Sie alle Ihre tests.
um ehrlich zu sein, ich denke, es wäre das einfachste für jemanden, um zu sehen, was die Probleme sind, durch ausführen der source code selbst.
Was sind die Arten von t1 und t2 im Objects.compare Beispiel? Ich versuche zu folgern, aber die Schichtung mein Typ-Inferenz über der compiler die Typ-Inferenz ist unlösbar. 🙂
Auch welche compiler verwenden Sie?
Sie haben zwei getrennte Probleme hier. Einer der Beantworter darauf hingewiesen, Sie könnte verwenden Sie die Methode verweist, die Sie sorta abgebürstet. Genauso wie Lambda-Ausdrücke kommen in beiden "explizit typisierte" und "implizit typisierte" Aromen, Methode, Referenzen kommen in "exakt" sind (überlastung) und "ungenau" (mehrere überladungen) Aromen. Entweder eine genaue Methode ref oder ein expliziter lambda-Ausdruck kann verwendet werden, um zusätzliche Eingabe von Informationen, wenn Sie nicht vorhanden ist. (Explizite Typ-Zeugen und Besetzungen können auch verwendet werden, aber sind oft größer Hämmer.)

InformationsquelleAutor Tranquility | 2014-06-26

Schreibe einen Kommentar