Kako raditi sa tokovima (streams) u Kotlinu?
sobes.tech АИ
Одговор од АИ
U Kotlinu za rad sa tokovima podataka (analogno Java 8 Streams API) koriste se funkcije proširenja za kolekcije, koje pruža standardna biblioteka funkcija. To nije poseban API, već skup metoda iz kotlin.collections.
Glavne operacije sa tokovima dele se na:
- Međuprostorne (Intermediate) operacije: Vraćaju novu kolekciju i "lenje" se (izvršavaju se samo pri pozivu terminalne operacije). Primeri:
filter,map,flatMap,distinct,sorted,take,drop. - Terminalne (Terminal) operacije: Završavaju niz operacija i vraćaju rezultat (ne kolekciju). Aktiviraju izvršenje svih međuprostornih operacija. Primeri:
forEach,reduce,fold,count,sum,average,min,max,toList,toSet,toMap.
Takođe postoji koncept sekvenci (sequences), koji obezbeđuje eksplicitnu lenjivost. Sekvence obrađuju elemente jedan po jedan po potrebi, što može biti efikasnije za velike kolekcije ili duge lance operacija:
- Kreiranje sekvence:
collection.asSequence() - Pretvaranje nazad u kolekciju:
sequence.toList()
// Primer korišćenja standardnih funkcija za obradu tokova
fun processCollection() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenSquares = numbers
.filter { it % 2 == 0 } // Međuprostorna operacija: filtriramo parne brojeve
.map { it * it } // Međuprostorna operacija: kvadriramo
println(evenSquares) // Terminalna operacija: prikazuje kolekciju (izvršava filtriranje i map)
val sumOfOdd = numbers
.filter { it % 2 != 0 } // Međuprostorna
.sum() // Terminalna (izvršava se): računa zbir neparnih
println(sumOfOdd)
}
// Primer korišćenja sekvenci
fun processSequence() {
val largeCollection = (1..1_000_000).toList()
// Sa kolekcijama (ne lenjive): filter i map će se izvršiti za sve elemente
val resultCollection = largeCollection
.filter { it % 2 == 0 }
.map { it * 2 }
.take(10) // take(10) se izvršava nakon filtriranja i map za sve
println("Result Collection size: ${resultCollection.size}")
// Sa sekvencama (lenjive): filter, map i take se izvršavaju po elementu
val resultSequence = largeCollection.asSequence()
.filter { it % 2 == 0 } // filter se izvršava za svaki element
.map { it * 2 } // map se izvršava za svaki prošli filter element
.take(10) // take(10) zaustavlja obradu nakon 10 elemenata
println("Result Sequence size: ${resultSequence.toList().size}") // toList() pokreće izvršenje sekvence
}
fun main() {
processCollection()
processSequence()
}
Tabela poređenja standardnih funkcija i sequences u pogledu lenjivosti:
| Osobina | Standardne funkcije kolekcija | Sequences |
|---|---|---|
| Lijenost | Nejasna lenjivost za međuprostorne operacije, ali terminalna operacija obrađuje ceo lanac | Jasna lenjivost: operacije se izvršavaju po elementu po potrebi |
| Efikasnost | Može biti manje efikasno za velike kolekcije i duge lance zbog međuprostornih kolekcija | Efikasnije za velike kolekcije i duge lance operacija |
| Primena | Pogodno za manje i srednje kolekcije | Pogodno za velike kolekcije ili operacije koje mogu biti prekinute ranije (take, find, first, any, all, none) |
Korišćenje standardnih funkcija na kolekcijama je najčešće dovoljno i kraće. Sequences se preporučuju kada je potrebna jasna lenjivost za optimizaciju performansi pri radu sa velikim količinama podataka.