Ich habe den Unterschied zwischen Collections.sortund untersucht list.sort, insbesondere in Bezug auf die Verwendung der Comparatorstatischen Methoden und ob Parametertypen in den Lambda-Ausdrücken erforderlich sind. Bevor wir beginnen, weiß ich, dass ich Methodenreferenzen verwenden könnte, z. B. Song::getTitleum meine Probleme zu lösen, aber meine Abfrage hier ist nicht so sehr etwas, das ich beheben möchte, sondern etwas, auf das ich eine Antwort haben möchte, dh warum behandelt der Java-Compiler dies so .
Das sind meine Erkenntnisse. Angenommen, wir haben einen ArrayListTyp Song, bei dem einige Songs hinzugefügt wurden. Es gibt drei 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 beider Arten von Sortiermethoden, die funktionieren, kein Problem:
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle()));
playlist1.sort(
Comparator.comparing(p1 -> p1.getTitle()));
Sobald ich anfange zu verketten thenComparing, passiert 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())
);
dh Syntaxfehler, weil es den Typ von p1nicht mehr kennt . Um dies zu beheben, füge ich den Typ Songzum ersten Parameter (zum Vergleichen) hinzu:
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 p laylist1.sort, dh die Liste, werden alle Kompilierungsfehler für beide folgenden thenComparingAufrufe behoben. Doch für Collections.sort, sie löst es für die erste, aber nicht das letzte. Ich habe getestet, dass mehrere zusätzliche Aufrufe hinzugefügt wurden, thenComparingund es wird immer ein Fehler für den letzten angezeigt, es sei denn, ich habe (Song p1)den Parameter eingegeben.
Nun habe ich dies weiter getestet, indem ich ein erstellt TreeSetund Folgendes verwendet habe 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())
);
Es passiert dasselbe wie in, denn TreeSetes gibt keine Kompilierungsfehler, aber Objects.comparebeim letzten Aufruf thenComparingwird ein Fehler angezeigt.
Kann jemand bitte erklären, warum dies geschieht und warum es überhaupt nicht nötig ist, es zu verwenden, (Song p1)wenn einfach die Vergleichsmethode aufgerufen wird (ohne weitere thenComparingAufrufe).
Eine andere Abfrage zum gleichen Thema ist, wenn ich dies tue TreeSet:
Set<Song> set = new TreeSet<Song>(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
dh den Typ Songaus dem ersten Lambda-Parameter für den Aufruf der Vergleichsmethode entfernen , es werden Syntaxfehler unter dem Aufruf zum Vergleichen und dem ersten Aufruf zum, thenComparingaber nicht zum letzten Aufruf von angezeigt thenComparing- fast das Gegenteil von dem, was oben geschah! Während für alle die anderen drei Beispiele , dh mit Objects.compare, List.sortund Collections.sortwenn ich entfernen , die erste Songparam Typ es zeigt Syntaxfehler für alle Anrufe.
Vielen Dank im Voraus.
Bearbeitet, um einen Screenshot von Fehlern aufzunehmen, die ich in Eclipse Kepler SR2 erhalten habe. Die ich seitdem gefunden habe, sind Eclipse-spezifisch, da sie beim Kompilieren mit dem JDK8-Java-Compiler in der Befehlszeile OK kompiliert werden.
