Ինչպես աշխատել 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-ը խորհուրդ է տրվում, երբ անհրաժեշտ է բացահայտ սպասում՝ օպտիմալացման համար մեծ տվյալների հետ աշխատելիս։