Kotlin'de akışlar (streams) ile nasıl çalışılır?
sobes.tech yapay zeka
AI'dan gelen yanıt
Kotlin'de, veri akışlarıyla (Java 8 Streams API'ye eşdeğer) çalışmak için, standart fonksiyon kitaplığında sağlanan koleksiyonlar için genişletme fonksiyonları kullanılır. Bu, ayrı bir API değil, kotlin.collections içindeki metodların bir kümesidir.
Ana akış işlemleri şunlara ayrılır:
- Ara işlemler: Yeni bir koleksiyon döner ve "tembel" (yalnızca terminal bir işlem çağrıldığında yürütülür). Örnekler:
filter,map,flatMap,distinct,sorted,take,drop. - Terminal işlemler: İşlem dizisini tamamlar ve bir sonuç döner (koleksiyon değil). Tüm ara işlemleri tetikler. Örnekler:
forEach,reduce,fold,count,sum,average,min,max,toList,toSet,toMap.
Ayrıca, diziler (sequences) kavramı da vardır ve bu, açık bir tembellik sağlar. Diziler, ihtiyaç duyulduğu anda öğeleri tek tek işler, bu da büyük koleksiyonlar veya uzun işlem zincirleri için daha verimli olabilir:
- Bir dizi oluşturma:
collection.asSequence() - Tekrar koleksiyona dönüştürme:
sequence.toList()
// Standart fonksiyonların akış işleme örneği
fun processCollection() {
val numbers = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val evenSquares = numbers
.filter { it % 2 == 0 } // Ara işlem: çift sayıları filtrele
.map { it * it } // Ara işlem: kare al
println(evenSquares) // Terminal işlem: koleksiyonu yazdır (filter ve map yürütülür)
val sumOfOdd = numbers
.filter { it % 2 != 0 } // Ara
.sum() // Terminal (tek sayıları toplar)
println(sumOfOdd)
}
// Diziler kullanımı örneği
fun processSequence() {
val largeCollection = (1..1_000_000).toList()
// Koleksiyonlar ile (tembel değil): filter ve map hemen tüm öğeler için yürütülür
val resultCollection = largeCollection
.filter { it % 2 == 0 }
.map { it * 2 }
.take(10) // take(10), filter ve map sonrası tümü için yürütülür
println("Sonuç Koleksiyon boyutu: ${resultCollection.size}")
// Diziler ile (tembel): filter, map ve take öğe öğe yürütülür
val resultSequence = largeCollection.asSequence()
.filter { it % 2 == 0 } // filter her öğe için sırayla yürütülür
.map { it * 2 } // map, filtreyi geçen her öğe için yürütülür
.take(10) // take(10), 10 öğeden sonra işlemi durdurur
println("Sonuç Dizi boyutu: ${resultSequence.toList().size}") // toList() dizinin yürütülmesini tetikler
}
fun main() {
processCollection()
processSequence()
}
Standart fonksiyonlar ve diziler arasındaki tembellik açısından karşılaştırma tablosu:
| Özellik | Standart koleksiyon fonksiyonları | Diziler |
|---|---|---|
| Tembellik | Ara işlemler için varsayılan tembellik, ancak terminal işlem tüm ara zinciri işler | Açık tembellik: işlemler ihtiyaç duyulduğu anda öğe öğe yürütülür |
| Verimlilik | Büyük koleksiyonlar ve uzun işlem zincirleri için ara koleksiyonlar nedeniyle daha az verimli olabilir | Büyük koleksiyonlar ve uzun işlem zincirleri için daha verimlidir |
| Uygulama | Küçük ve orta koleksiyonlar için uygundur | Büyük koleksiyonlar veya erken durdurulabilen işlemler için uygundur (take, find, first, any, all, none) |
Standart fonksiyonların kullanımı genellikle yeterlidir ve daha kısadır. Diziler, büyük veri hacimleriyle çalışırken performansı optimize etmek için açık tembellik gerekiyorsa önerilir.