Sobes.tech
Middle

Ինչպես աշխատել Kotlin- ում հոսքերի (streams) հետ?

sobes.tech AI

Պատասխան AI-ից

Կոտլինում տվյալների հոսքերի (Java 8 Streams API-ի համարժեք) հետ աշխատելու համար օգտագործվում են ընդլայնման ֆունկցիաներ հավաքածուների համար, որոնք տրամադրվում են ստանդարտ ֆունկցիաների գրադարանով: Սա ոչ թե առանձին API է, այլ մեթոդների հավաքածու kotlin.collections:

Հոսքերի հիմնական գործողությունները բաժանվում են.

  • Միջնորդական (Intermediate operations): Վերադարձնում են նոր հավաքածու և «սպասում» են (կատարվում են միայն երբ կանչվում է տերմինալ գործողությունը): Օրինակներ՝ filter, map, flatMap, distinct, sorted, take, drop.
  • Տերմինալ (Terminal operations): Ավարտում են գործողությունների շարքը և վերադարձնում արդյունք (չհավաքածու): Դրանք գործարկում են բոլոր միջնորդական գործողությունները: Օրինակներ՝ forEach, reduce, fold, count, sum, average, min, max, toList, toSet, toMap.

Կա նաև կոնցեպցիա՝ հետևական հոսքեր (sequences), որը ապահովում է բացահայտ «սպասում»: Sequences-ը մշակում են տարրերը մեկ առ մեկ ըստ անհրաժեշտության, ինչը կարող է լինել ավելի արդյունավետ մեծ հավաքածուների կամ երկար շղթաների համար:

  • Հետևականության ստեղծում՝ collection.asSequence()
  • Վերածում հավաքածու՝ sequence.toList()
// Օրինակ՝ ստանդարտ ֆունկցիաների օգտագործում հոսքային մշակման համար
fun processCollection() {
    val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    val evenSquares = numbers
        .filter { it % 2 == 0 } // Միջնորդական գործողություն՝ ֆիլտրում զույգ թվեր
        .map { it * it }     // Միջնորդական գործողություն՝ քառակուսիներ

    println(evenSquares) // Տերմինալ գործողություն՝ ցուցադրում է հավաքածուն (կատարվում է ֆիլտրում և map)

    val sumOfOdd = numbers
        .filter { it % 2 != 0 } // Միջնորդական
        .sum()                // Տերմինալ (հաշվարկում է անհավասար թվերի գումարը)

    println(sumOfOdd)
}

// Օրինակ՝ հետևականությունների օգտագործում
fun processSequence() {
    val largeCollection = (1..1_000_000).toList()

    // Հավաքածուներով (չսպասում է): filter և map կատարվում են բոլոր տարրերի համար
    val resultCollection = largeCollection
        .filter { it % 2 == 0 }
        .map { it * 2 }
        .take(10) // take(10) կատարվում է ֆիլտրումից և map-ից հետո բոլոր տարրերի համար

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

    // Հետևականություններով (սպասում է): filter, map և take կատարվում են տարր առ տարր
    val resultSequence = largeCollection.asSequence()
        .filter { it % 2 == 0 } // filter կատարվում է յուրաքանչյուր տարրով հերթով
        .map { it * 2 }     // map կատարվում է յուրաքանչյուր անցած ֆիլտրով տարրով
        .take(10)         // take(10) դադարեցնում է մշակումը 10 տարրից հետո

    println("Result Sequence size: ${resultSequence.toList().size}") // toList() հրահրում է հետևականության կատարմանը
}

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

Տեղեկացվում է ստանդարտ ֆունկցիաների և sequences-ի համեմատությունը՝ ըստ սակավության:

Գծանշում Ստանդարտ հավաքածուների ֆունկցիաներ Sequences
Սպասում Անհայտ սպասում միջնորդական գործողությունների համար, բայց տերմինալ գործողությունը ամբողջ շղթան ամբողջությամբ է մշակվում Բացահայտ սպասում՝ գործողությունները կատարվում են տարր առ տարր ըստ անհրաժեշտության
Արդյունավետություն Կարող է լինել ոչ այնքան արդյունավետ մեծ հավաքածուների և երկար շղթաների համար՝ միջնորդական հավաքածուների պատճառով Ավելի արդյունավետ մեծ հավաքածուների և երկար շղթաների համար
Հիմնադրամ Հարմար է փոքր և միջին հավաքածուների համար Հարմար է մեծ հավաքածուների կամ այն գործողությունների համար, որոնք կարող են վաղաժամ ընդհատվել (take, find, first, any, all, none)

Ստանդարտ ֆունկցիաների օգտագործումը հավաքածուների վրա հաճախ բավական է և ավելի կարճ: Sequences-ը խորհուրդ է տրվում, երբ անհրաժեշտ է բացահայտ սպասում՝ օպտիմալացման համար մեծ տվյալների հետ աշխատելիս։