Warum „einfache“ Sortierung in Kotlin den Code zerstört?
\nHallo, Kollege! Wenn du jemals in Kotlin geschrieben und versucht hast, eine Liste von Aufgaben zuerst nach Datum und dann nach Priorität zu sortieren, bist du sicherlich auf eine Situation gestoßen, in der das Ergebnis wie eine zufällige Ansammlung aussieht. Du bist nicht allein – die Frage „Sort collection by multiple fields in Kotlin“ hat tausende Aufrufe auf Stack Overflow gesammelt. Es scheint einfach, oder? Aber der Teufel steckt, wie immer, im Detail.
\nIn diesem Artikel analysieren wir die Top-Fehler bei der Sortierung nach mehreren Feldern in Kotlin, die selbst erfahrene Entwickler machen. Du erfährst, wie sortedWith funktioniert, warum compareBy und thenBy deine besten Freunde sind und wie du keine Daten durch null verlierst. Los geht's!
Fehler Nr. 1: Sortierung wie in Java – manuell mit Comparator
\nKotlin ist nicht Java. Aber viele, die aus der Java-Welt kommen, schreiben:
\nval list = listOf(\n User("Alice", 25),\n User("Bob", 20),\n User("Charlie", 25)\n)\n\nval sorted = list.sortedWith(Comparator { a, b ->\n val ageCompare = a.age.compareTo(b.age)\n if (ageCompare != 0) ageCompare else a.name.compareTo(b.name)\n})\n\nJa, das funktioniert. Aber es ist schrecklich lesbar, und du verlierst leicht den Überblick in den if-else-Ketten. Kotlin bietet eine elegante Möglichkeit – Comparator-Funktionen.
Wie macht man es richtig?
\nval sorted = list.sortedWith(compareBy<User> { it.age }.thenBy { it.name })\n\nKurz, klar, ohne überflüssige Logik. compareBy erstellt den primären Comparator, und thenBy fügt sekundäre Felder hinzu. Das ist die Sortierung nach mehreren Feldern in Kotlin in ihrer idealen Form.
Fehler Nr. 2: Ignorieren von null bei der Sortierung
\nAngenommen, wir haben eine Liste von Aufgaben, bei denen deadline null sein kann. Wenn du einfach schreibst:
tasks.sortedBy { it.deadline }\n\n…erhältst du eine NullPointerException. Kotlin ist streng mit null, und das ist großartig. Aber was, wenn null in Ordnung ist?
\nLösung: nullsFirst / nullsLast
\nVerwende spezielle Wrapper:
\nval sorted = tasks.sortedWith(\n compareBy<Task>(nullsLast()) { it.deadline }\n .thenBy { it.priority }\n)\n\nHier platziert nullsLast() alle null-Daten ans Ende der Liste. Es gibt auch nullsFirst() – umgekehrt. Das löst das Problem, und deine Sortierung von Kotlin-Sammlungen wird sicher.
Fehler Nr. 3: Verwechslung von sortedBy und sortedWith
\nViele Anfänger schreiben:
\nlist.sortedBy { it.age }.sortedBy { it.name }\n\nUnd wundern sich, dass die Sortierung nach Namen die Sortierung nach Alter „überschreibt“. sortedBy erstellt jedes Mal eine neue Liste und sortiert nur nach einem Feld. Der letzte Aufruf ist der wichtigste.
Wie behebt man das?
\nVerwende sortedWith mit einer compareBy-Kette:
list.sortedWith(compareBy({ it.age }, { it.name }))\n\nOder die mehrzeilige Variante für komplexe Logik:
\nlist.sortedWith(compareBy<Person> { it.age }.thenByDescending { it.name })\n\nMerke dir: Ein Aufruf von sortedWith – eine Sortierung nach mehreren Feldern.
\n\nFehler Nr. 4: Sortierung in umgekehrter Reihenfolge – an der falschen Stelle
\nManchmal muss man nach aufsteigendem Alter, aber absteigendem Namen sortieren. Typischer Fehler:
\nlist.sortedByDescending { it.age }.sortedBy { it.name }\n\nWieder das gleiche Problem – die zweite Sortierung zerstört die erste. Der richtige Ansatz:
\nval sorted = list.sortedWith(\n compareBy<Person> { it.age }\n .thenByDescending { it.name }\n)\n\nOder für volle Kontrolle:
\nval sorted = list.sortedWith(\n compareBy(Person::age).thenByDescending(Person::name)\n)\n<