Sobes.tech
Middle

Kā strādāt ar straumēm (streams) Kotlin?

sobes.tech AI

Atbilde no AI

Kotlinā datu plūsmu (Java 8 Streams API analogs) darbam tiek izmantotas kolekciju paplašināšanas funkcijas, kas nodrošinātas standarta funkciju bibliotēkā. Tas nav atsevišķs API, bet metožu kopums kotlin.collections:

Galvenās plūsmu operācijas ir sadalītas:

  • Starpposma (Intermediate operations): Atgriež jaunu kolekciju un ir "gudras" (tiek izpildītas tikai izsaucot galīgo operāciju). Piemēri: filter, map, flatMap, distinct, sorted, take, drop.
  • Galīgās (Terminal operations): Pabeidz operāciju virkni un atgriež rezultātu (ne kolekciju). Izpilda visas starpposma operācijas. Piemēri: forEach, reduce, fold, count, sum, average, min, max, toList, toSet, toMap.

Ir arī koncepcija — secības (sequences), kas nodrošina skaidru "gudru" (lētu) izpildi. Sekas apstrādā elementus pa vienam pēc nepieciešamības, kas var būt efektīvāk lielām kolekcijām vai garām operāciju ķēdēm:

  • Sekvences izveide: collection.asSequence()
  • Pārveidošana atpakaļ uz kolekciju: sequence.toList()
// Standarta funkciju izmantošanas piemērs plūsmas apstrādei
fun processCollection() {
    val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    val evenSquares = numbers
        .filter { it % 2 == 0 } // Starpposma operācija: filtrē pāra skaitļus
        .map { it * it }     // Starpposma operācija: kvadrāti

    println(evenSquares) // Galīgā operācija: izvada kolekciju (izpilda filtrēšanu un map)

    val sumOfOdd = numbers
        .filter { it % 2 != 0 } // Starpposma
        .sum()                // Galīgā (summa nespējīgajiem)

    println(sumOfOdd)
}

// Seku izmantošanas piemērs
fun processSequence() {
    val largeCollection = (1..1_000_000).toList()

    // Ar kolekcijām (ne lēni): filter un map tiek izpildīti visiem elementiem uzreiz
    val resultCollection = largeCollection
        .filter { it % 2 == 0 }
        .map { it * 2 }
        .take(10) // take(10) tiek izpildīts pēc filtrēšanas un map visiem

    println("Result Collection size: ${resultCollection.size}")

    // Ar sekām (lēni): filter, map un take tiek izpildīti pa vienam elementam
    val resultSequence = largeCollection.asSequence()
        .filter { it % 2 == 0 } // filter tiek izpildīts katram elementam pa vienam
        .map { it * 2 }     // map tiek izpildīts katram pārbaudītajam elementam
        .take(10)         // take(10) pārtrauc apstrādi pēc 10 elementiem

    println("Result Sequence size: ${resultSequence.toList().size}") // toList() izpilda sekas
}

fun main() {
    processCollection()
    processSequence()
}

Salīdzinājuma tabula par standarta funkcijām un sekām:

Īpašība Standarta kolekciju funkcijas Sequences
Lēnuma Netieša lēnuma starpposma operācijām, bet galīgā operācija apstrādā visu ķēdi pilnībā Skaidra lēnuma: operācijas tiek izpildītas pa vienam elementam pēc nepieciešamības
Efektivitāte Var būt mazāk efektīva lielām kolekcijām un garām operāciju ķēdēm dēļ starpposma kolekcijām Efektīvāka lielām kolekcijām un garām operāciju ķēdēm
Piemērošana Piemērota mazām un vidējām kolekcijām Piemērota lielām kolekcijām vai operācijām, kuras var būt agrāk pārtrauktas (take, find, first, any, all, none)

Standarta funkcijas kolekcijām bieži ir pietiekamas un ir kodu ziņā īsākas. Sequences ieteicamas, ja nepieciešama skaidra lēnuma efektivitāte, strādājot ar lieliem datu apjomiem.