Jak pracovat s proudy (streams) v Kotlinu?
sobes.tech AI
Odpověď od AI
V Kotlinu se pro práci s datovými proudy (analogicky Java 8 Streams API) používají rozšiřující funkce pro kolekce, které jsou poskytovány knihovnou standardních funkcí. Nejedná se o samostatné API, ale o sadu metod z kotlin.collections.
Hlavní operace s proudy jsou rozděleny na:
- Meziprodukční (Intermediate) operace: Vrací novou kolekci a jsou "líné" (provádí se pouze při volání terminální operace). Příklady:
filter,map,flatMap,distinct,sorted,take,drop. - Terminální (Terminal) operace: Ukončují sekvenci operací a vracejí výsledek (nikoliv kolekci). Spouštějí vykonání všech meziprodukčních operací. Příklady:
forEach,reduce,fold,count,sum,average,min,max,toList,toSet,toMap.
Existuje také koncept sekvencí (sequences), který zajišťuje explicitní lenivost. Sekvence zpracovávají prvky po jednom podle potřeby, což může být efektivnější pro velké kolekce nebo dlouhé řetězce operací:
- Vytvoření sekvence:
collection.asSequence() - Převod zpět na kolekci:
sequence.toList()
// Příklad použití standardních funkcí pro zpracování proudů
fun processCollection() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenSquares = numbers
.filter { it % 2 == 0 } // Meziprodukční operace: filtrujeme sudá čísla
.map { it * it } // Meziprodukční operace: umocňujeme na druh
println(evenSquares) // Terminální operace: vypisujeme kolekci (provádí filtraci a map)
val sumOfOdd = numbers
.filter { it % 2 != 0 } // Meziprodukční
.sum() // Terminální (vykonávaná): spočítá součet lichých
println(sumOfOdd)
}
// Příklad použití sekvencí
fun processSequence() {
val largeCollection = (1..1_000_000).toList()
// S kolekcemi (ne líně): filter a map se provedou pro všechny prvky
val resultCollection = largeCollection
.filter { it % 2 == 0 }
.map { it * 2 }
.take(10) // take(10) se provádí po filtraci a map pro všechny
println("Result Collection size: ${resultCollection.size}")
// S sekvencemi (líně): filter, map a take se provádějí po jednom prvku
val resultSequence = largeCollection.asSequence()
.filter { it % 2 == 0 } // filter se provádí pro každý prvek
.map { it * 2 } // map se provádí pro každý projítý prvek
.take(10) // take(10) zastaví zpracování po 10 prvcích
println("Result Sequence size: ${resultSequence.toList().size}") // toList() spouští sekvenci
}
fun main() {
processCollection()
processSequence()
}
Porovnávací tabulka standardních funkcí a sequences z hlediska lenivosti:
| Vlastnost | Standardní funkce kolekcí | Sequences |
|---|---|---|
| Línost | Nezřejmá lenivost u meziprodukčních operací, ale terminální operace zpracovává celý řetězec najednou | Explicitní lenivost: operace se provádějí po jednom prvku podle potřeby |
| Efektivita | Může být méně efektivní pro velké kolekce a dlouhé řetězce operací kvůli meziprodukčním kolekcím | Efektivnější pro velké kolekce a dlouhé řetězce operací |
| Použití | Vhodné pro malé a střední kolekce | Vhodné pro velké kolekce nebo operace, které lze předčasně ukončit (take, find, first, any, all, none) |
Použití standardních funkcí na kolekcích je většinou dostačující a stručnější. Sequences jsou doporučovány, když je potřeba explicitní lenivost pro optimalizaci výkonu při práci s velkými objemy dat.