Kotlin Sequences
Java 8 ile beraber gelen Stream‘lerin Kotlin karşılığı Sequence
‘lardır. Java ile aralarında bir isim çakışması olmasın diye Kotlin’de Sequence adı kullanılmış.
Collection’lar ve map
, filter
, groupBy
gibi higher-order fonksiyonlar ile veri işlemenin ne kadar kolay olduğunu bir önceki yazıda görmüştük. Bu yazıda da Sequence’lardan yani lazy Collection
‘lardan bahsedeceğiz. Sequence’lar sayesinde java 8 öncesini destekleyen platformlarda (örneğin Android) stream’lerın sağladığı avantajları kullanabilirsiniz. Sequence’ların, stream’lerden farklı olarak, birden fazla CPU’da çalışma destekleri yoktur.
Bu yazıda yer alan örneklerde aşağıdaki Payment
data sınıfını kullanacağız. Payment sınıfı “free to play” bir oyunun uygulama içi yapılan satın almalarını temsil ediyor. Örneğin 101 Plus oyununda kullanıcılar oyun içerisinden kredi kartları ile ödeme yapıp sadece oyun içinde kullanabilecekleri sanal paraları (coins) satın alabilirler. Payment sınıfı satın almanın ne zaman, kim tarafından ve hangi platformdan yapıldığı gibi bilgileri tutuyor.
Android platformundan yapılan satın almaların TRY (Türk Lirası) cinsinden toplamını bulmak için filter ve map higher-order fonksiyonlarını kullabiliriz. Doların 3.6 Euro’nun da 3.9 lira olduğunu varsayarsak aşağıdaki örnek bize TRY cinsinden toplamı verir.
Collection’lar üzerinde çalışan map ve filter fonksiyonları hesaplamalar arasında geçici collection’lar oluştururlar. paymentList
‘e Android platformu filtresi uyguladığımızda içerisinde sadece Android platformundan yapılan satın almaların olduğu ara bir liste oluşur. Daha sonra bu ara listeyi map
fonksiyonu alır ve map de TRY cinsinden fiyatların olduğu yeni bir ara liste oluşturur. Son olarak da olusan son listenin içindeki fiyatları toplamak için sum
fonksiyonunu kullanabiliriz.
Sequence’lar, hesaplamalar arasında geçici collection’lar oluşturmadan collection’lar üzerinde çalışabilme imkanı sağlar. Yukarıda yapılan işlemin aynısı Sequence kullanılarak aşağıdaki gibi yapılabilir.
Yukarıdaki kodun ilk örnekten tek farkı, filter
ve map
fonksiyonlarını doğrudan liste üzerinde değil, asSequence()
metodu ile oluşturduğumuz bir sequence üzerinde çalıştırmasıdır.
Kotlin’de Sequence’lar, Collection’lar ile aynı API metodlarına sahip oldukları için Collection’lar ile yapabildiğiniz herşeyi Sequence’lar ile de yapabilirsiniz. Sequence’lar, Collection’ların aksine lazy
çalışırlar. Sequence’lar üzerinde yapılan işlemler ara işlemler (intermediate) ve sonlandırıcı işlemler (terminal) olmak üzere ikiye ayrılır. Ara işlemler sonuç olarak yeni bir Sequence dönerler. Sonlandırıcı işlemler sonuç olarak bir collection ya da herhangi bir object (sayı, sequence içindeki herhangi bir eleman …) dönerler.
Aşağıda asSequence()
metodu ile oluşturulan bir Sequence’a önce map sonra da filter ara işleminin uygulandığını görüyoruz. Bu örnek kod parçası çalıştırıldığında ekrana hiçbir şey yazmaz. Çünkü sequence’larda ara işlemler lazy
olarak çalıştırılır.
Sequence’ı sonlandırıp bir sonuç elde etmek için toList()
metodu kullanabiliriz. Sonlandırıcı işlem tüm ara işlemlerin çalıştırılmasını sağlar.
Sequence Oluşturma
Sequence’ları iki farklı şekilde oluşturabiliriz.
- Herhangi bir Iterable‘dan
asSequence()
metodu ile - generateSequence standard library fonksiyonu ile
generateSequence
fonksiyonu iki parametre alıyor. Birinci parametre sequence’in başlangıc elemanı, ikinci parametre ise bir önceki elemanı kullanarak sequence’ta sıradaki elemanı hesaplayan lambda fonksiyonu. Aşağıda Fibonacci sayılarını hesaplayan bir sequence oluşturma örneği görüyorsunuz:
generateSequence
fonksiyonunun parametre olarak sadece bir generator fonksiyon alan versiyonu da var. Sonsuz sayıda ve rastgele Payment
üretmek için aşağıdaki generator kullanılabilir:
Payment object’lerinden oluşan sequence’ı ve standard library’deki sequence ve collection metodlarını kullanarak bir kaç örnek hesaplama yapalım. Rastgele oluşturduğumuz Payment’lardan 100 tanesini kullanarak her platform için ayrı ayrı satın alma adetlerini aşağıdaki gibi hesaplayabiliriz.
Currency’yi hesaba katmadan tüm platformlardan elde edilen geliri aşağıdaki gibi hesaplayabiliriz:
Currency’yi hesaba katmadan platformların ayrı ayrı gelirlerini aşağıdaki gibi hesaplayabiliriz:
Görüldüğü gibi kullanım şekli bakımından Sequence’ların Collection’lardan bir farkı yok. Eleman sayısı çok fazla olan Collection’lar üzerinde çalışıyorsak Sequence kullanmak geçici (temporary) collection’ların oluşmasını önleyeceği için daha avantajlı olabilir.