Sobes.tech
Middle

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.