Ich habe den Unterschied zwischen Collections.sort
und untersucht list.sort
, insbesondere in Bezug auf die Verwendung der Comparator
statischen 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::getTitle
um 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 ArrayList
Typ 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 p1
nicht mehr kennt . Um dies zu beheben, füge ich den Typ Song
zum 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 thenComparing
Aufrufe 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, thenComparing
und 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 TreeSet
und 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 TreeSet
es gibt keine Kompilierungsfehler, aber Objects.compare
beim letzten Aufruf thenComparing
wird 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 thenComparing
Aufrufe).
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 Song
aus dem ersten Lambda-Parameter für den Aufruf der Vergleichsmethode entfernen , es werden Syntaxfehler unter dem Aufruf zum Vergleichen und dem ersten Aufruf zum, thenComparing
aber 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.sort
und Collections.sort
wenn ich entfernen , die erste Song
param 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.