In Kotlin sind Sequence faule Sequenzen, die es ermöglichen, effizient mit großen oder sogar potenziell unendlichen Datenmengen zu arbeiten. Die Operationen auf Sequence (wie map, filter) werden nicht sofort ausgeführt; stattdessen wird eine Kette von Aktionen aufgebaut, und die Berechnung erfolgt nur bei Bedarf (bei einer terminalen Operation, z.B. toList).
Warum ist das wichtig:
Codebeispiel:
val numbers = generateSequence(1) { it + 1 } .filter { it % 2 == 0 } .map { it * it } .take(5) .toList() println(numbers) // [4, 16, 36, 64, 100]
In diesem Beispiel werden nur die 5 ersten Elemente der Sequenz tatsächlich berechnet, obwohl sie potenziell unendlich ist.
Wann Sequence verwenden:
Kann man garantieren, dass Operatoren wie
mapundfilterin normalen Sammlungen von Kotlin ebenfalls faul sind? Warum?
Antwort: Nein, die standardmäßigen Sammlungsoperationen (List.map, List.filter usw.) in Kotlin sind streng gierig. Jede Operation erstellt eine zwischenzeitliche Sammlung und verarbeitet sofort alle Elemente. Faulheit wird nur bei der Verwendung von Sequence unterstützt.
Beispiel:
val data = listOf(1,2,3,4) val mapped = data.map { println("Mapping $it"); it * 2 } // Drucken sofort alle Werte
Geschichte
In einem Projekt, das große CSV-Dateien (bis zu einem Gigabyte beim Schreiben) bearbeitet, wurde die Sammlung zunächst vollständig in eine List geladen, bevor chain map/filter angewendet wurden. Die Anwendung „legte sich“ aufgrund von OutOfMemory – das Problem wurde gelöst, indem List durch Sequence ersetzt wurde, dessen map/filter keine riesigen zwischenzeitlichen Listen erstellte.
Geschichte
Ein Backend-Service zur Aggregation von Berichten aus mehreren Datenbanken sammelte zunächst die Suchergebnisse in einer List und filterte sie dann: Die Anfragen wurden langsam, es traten GC-Lags auf. Der Wechsel zu einem Generator + Sequence ermöglichte die Aggregation von Daten in Echtzeit und reduzierte die Verzögerungen erheblich.
Geschichte
Ein von Java migriertes Projekt verwendete die standardmäßigen Erweiterungen von Kotlin (map, filter), ohne zu Sequence zu wechseln, während mit großen Datenströmen gearbeitet wurde, in der Annahme, dass der Code faul arbeitet, wie Streams in Java 8. Der Fehler führte zu ernsthaften Speicherlecks und plötzlichen Abstürzen im Produktionsbetrieb.