Hogyan dolgozzunk a Kotlinban a stream-ekkel?
sobes.tech MI
Válasz az MI-től
Kotlinben adatfolyamokkal (Java 8 Streams API-hoz hasonló) történő munkához a gyűjteményekhez kiterjesztő függvényeket használnak, amelyeket a standard függvénykönyvtár biztosít. Ez nem egy külön API, hanem a kotlin.collections metódusainak készlete.
A fő műveletek az adatfolyamokkal a következők szerint oszlanak:
- Közbenső (Intermediate) műveletek: Új gyűjteményt adnak vissza, és "lusta" módon hajtódnak végre (csak a végső művelet hívásakor). Példák:
filter,map,flatMap,distinct,sorted,take,drop. - Végső (Terminal) műveletek: Befejezik a műveletsorozatot, és eredményt adnak vissza (nem gyűjteményt). Aktiválják az összes közbenső művelet végrehajtását. Példák:
forEach,reduce,fold,count,sum,average,min,max,toList,toSet,toMap.
Emellett létezik az szekvenciák (sequences) fogalma, amely explicit módon biztosítja a lustaságot. A szekvenciák elemeket egymás után dolgoznak fel, szükség szerint, ami hatékonyabb lehet nagy gyűjtemények vagy hosszú műveletsorozatok esetén:
- Szekvencia létrehozása:
collection.asSequence() - Visszaalakítás gyűjteménnyé:
sequence.toList()
// Példa a standard függvények adatfolyam-kezelésére
fun processCollection() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenSquares = numbers
.filter { it % 2 == 0 } // Közbenső művelet: páros számok szűrése
.map { it * it } // Közbenső művelet: négyzetre emelés
println(evenSquares) // Végső művelet: gyűjtemény kiírása (a szűrés és a map végrehajtása)
val sumOfOdd = numbers
.filter { it % 2 != 0 } // Közbenső
.sum() // Végső (végrehajtott): páratlanok összege
println(sumOfOdd)
}
// Szekvencia használat példája
fun processSequence() {
val largeCollection = (1..1_000_000).toList()
// Gyűjteményekkel (nem lustán): a filter és map az összes elemre végrehajtódik
val resultCollection = largeCollection
.filter { it % 2 == 0 }
.map { it * 2 }
.take(10) // take(10) a filter és map után hajtódik végre minden elemre
println("Result Collection size: ${resultCollection.size}")
// Szekvenciákkal (lustán): a filter, map és take elem-enként végrehajtódik
val resultSequence = largeCollection.asSequence()
.filter { it % 2 == 0 } // filter minden elemre
.map { it * 2 } // map minden átment elemre
.take(10) // take(10) megállítja a feldolgozást 10 elem után
println("Result Sequence size: ${resultSequence.toList().size}") // toList() végrehajtja a szekvencia futtatását
}
fun main() {
processCollection()
processSequence()
}
Az összehasonlító táblázat a standard függvények és a sequences között a lustaság szempontjából:
| Jellemző | Standard gyűjteményfüggvények | Sequences |
|---|---|---|
| Lustaság | Rejtett lustaság a közbenső műveleteknél, de a végső művelet az egész láncot feldolgozza | Egyértelmű lustaság: a műveletek elem-enként végrehajtódnak szükség szerint |
| Hatékonyság | Kevésbé hatékony lehet nagy gyűjtemények és hosszú láncok esetén a közbenső gyűjtemények miatt | Hatékonyabb nagy gyűjtemények és hosszú láncok esetén |
| Alkalmazás | Kisebb és közepes gyűjteményekhez alkalmas | Nagy gyűjteményekhez vagy olyan műveletekhez, amelyek korán megszakíthatók (take, find, first, any, all, none) |
A standard függvények gyűjteményeken való használata általában elegendő és tömörebb. A sequences akkor ajánlottak, ha explicit lustaságra van szükség a nagy adatmennyiség hatékony kezelése érdekében.