Wie arbeitet man mit Streams in Kotlin?
sobes.tech KI
Antwort von AI
In Kotlin werden für die Arbeit mit Datenströmen (ähnlich Java 8 Streams API) Erweiterungsfunktionen für Sammlungen verwendet, die von der Standardfunktionsbibliothek bereitgestellt werden. Es ist keine separate API, sondern eine Sammlung von Methoden in kotlin.collections.
Die wichtigsten Operationen mit Strömen sind:
- Zwischenoperationen: Sie geben eine neue Sammlung zurück und sind "faul" (werden nur bei Aufruf einer terminalen Operation ausgeführt). Beispiele:
filter,map,flatMap,distinct,sorted,take,drop. - Terminaloperationen: Beenden die Operationenfolge und geben ein Ergebnis zurück (keine Sammlung). Sie lösen die Ausführung aller Zwischenoperationen aus. Beispiele:
forEach,reduce,fold,count,sum,average,min,max,toList,toSet,toMap.
Es gibt auch das Konzept der Sequenzen (sequences), das eine explizite Faulheit bietet. Sequenzen verarbeiten Elemente einzeln nach Bedarf, was bei großen Sammlungen oder langen Operationenketten effizienter sein kann:
- Erstellung einer Sequenz:
collection.asSequence() - Rückumwandlung in eine Sammlung:
sequence.toList()
// Beispiel für die Verwendung von Standardfunktionen für die Flussverarbeitung
fun processCollection() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenSquares = numbers
.filter { it % 2 == 0 } // Zwischenoperation: filtert gerade Zahlen
.map { it * it } // Zwischenoperation: quadriert
println(evenSquares) // Terminaloperation: gibt die Sammlung aus (führt filter und map aus)
val sumOfOdd = numbers
.filter { it % 2 != 0 } // Zwischen
.sum() // Terminal (berechnet die Summe der ungeraden)
println(sumOfOdd)
}
// Beispiel für die Verwendung von Sequenzen
fun processSequence() {
val largeCollection = (1..1_000_000).toList()
// Mit Sammlungen (nicht faul): filter und map werden sofort für alle Elemente ausgeführt
val resultCollection = largeCollection
.filter { it % 2 == 0 }
.map { it * 2 }
.take(10) // take(10) wird nach filter und map für alle ausgeführt
println("Ergebnis Sammlung Größe: ${resultCollection.size}")
// Mit Sequenzen (faul): filter, map und take werden elementweise ausgeführt
val resultSequence = largeCollection.asSequence()
.filter { it % 2 == 0 } // filter wird für jedes Element in Reihenfolge ausgeführt
.map { it * 2 } // map wird für jedes Element ausgeführt, das den Filter passiert
.take(10) // take(10) stoppt die Verarbeitung nach 10 Elementen
println("Ergebnis Sequenz Größe: ${resultSequence.toList().size}") // toList() löst die Ausführung der Sequenz aus
}
fun main() {
processCollection()
processSequence()
}
Vergleichstabelle der Standardfunktionen und Sequenzen hinsichtlich Faulheit:
| Eigenschaft | Standardfunktionen der Sammlungen | Sequenzen |
|---|---|---|
| Faulheit | Implizite Faulheit bei Zwischenoperationen, aber die Terminaloperation verarbeitet die gesamte Zwischenkette | Explizite Faulheit: Operationen werden elementweise nach Bedarf ausgeführt |
| Effizienz | Kann bei großen Sammlungen und langen Operationenketten aufgrund von Zwischenkollektionen weniger effizient sein | Effizienter bei großen Sammlungen und langen Operationenketten |
| Anwendung | Geeignet für kleine und mittlere Sammlungen | Geeignet für große Sammlungen oder Operationen, die frühzeitig abgebrochen werden können (take, find, first, any, all, none) |
Die Verwendung von Standardfunktionen auf Sammlungen ist meist ausreichend und kürzer. Sequenzen werden empfohlen, wenn explizite Faulheit zur Leistungsoptimierung bei der Arbeit mit großen Datenmengen erforderlich ist.