Kotlin Collections
Kotlin’de collection’lar, java collection library’leri üzerine yazılmış yardımcı sınıflar ve extension methodlardan oluşur. Kotlin programlama dilinin tasarımcıları, list
, map
ve set
gibi veriyapılarını sıfırdan yazmak yerine, Kotlin collection altyapısını, mevcut java sınıflarının üzerine kurma kararı vermişler.
Kotlin projesinin başındaki adam Andrey Breslav’dan bir alıntı yaparak kod örneklerine geçelim:
“Kotlin relies on Java libraries but makes them better, mostly through extensions but sometimes with compiler-supported techniques (collections, arrays, primitives).”
- Andrey Breslav, JetBrains
Kotlin’de collection’lar siz aksini belirtmedikçe read-only
‘dir. Liste oluşturmak için standard library içindeki listOf
ve mutableListOf
metodlarını kullanabiliriz.
listOf
metodu List<out T>
tipinde bir liste döner. listOf
metodundan aldığımız referans ile listeye eleman ekleyip çıkartamayız.
İçeriğini zaman içinde değiştirmek istediğimiz bir liste oluşturmak istersek mutableListOf
metodunu kullanabiliriz, bu metod bize MutableList
tipinde bir referans döner.
Kotlin’de şimdilik immutable
collection’lar yok. Ben bu yazıyı hazırlarken en son Kotlin versiyonu 1.1’di. Read-only
ve immutable
kavramlarını karıştırmamak lazım. immutable
bir collection bir kere oluşturulduktan sonra güncellenemez. Örnek olarak Guava Immutable Collections sınıflarına bakabilirsiniz.
Bizim elimizde mutable
bir collection’ı gösteren read-only bir referans olabilir. Biz read-only referansımız ile collection’ı güncelleyemeyiz fakat alt taraftaki mutable
collection bizim kontrolümüz dışında güncellenebilir. Aşağıdaki örnekte List<out T>
‘nin immutable değil read-only bir tip olduğunu görebilirsiniz:
Aşağıdaki örnek de Kotlin-Java geçişi sırasınra listenin read-only özelliğini bir işe yaramayacağını gösteriyor.
Kotlin collection’larının Java’dakilerden bir farkı da covariant
olmalarıdır. Java’da generic collection’lar invariant
‘tır. Örneğin java’da List<Number>
tipindeki bir referansa List<Integer>
tipinde bir referans ataması yapamayız.
Aşağıdaki java örneğini derlemeye çalıştığımızda Incompatiple Types
hatası alırız. Bu sayede java compiler numbers
referansı üzerinden Integer listesine Double
tipinde bir eleman eklenmesini önlemiş olur.
Java array
‘leri covariant
‘tır. Aşağıdaki kod problemsiz bir şekilde derlenir fakat çalıştırıldığında java.lang.ArrayStoreException
fırlatır.
Kotlin collection’ları covariant
olduğu için Integer listesini Number listesi yerine kullanabiliriz. Fakat Number listesi arayüzünden eriştiğimiz Integer listesini değitiremeyiz (ekleme ve çıkarma yapamayız).
Covariance ve Invariance hakkında daha detaylı bilgi için Effective Java
kitabının 5. bölümüne (Generics) bakabilirsiniz.
Kotlin standard library’de bilmemiz gereken ve collection’lar ile çalışmayı kolaylaştıran birçok extension metod var. map
, flatMap
, fold
, filter
, distinct
, average
, groupBy
, reduce
bu extension’lardan sadece bazıları.
Tek tek bu extension metodlarının ne yaptığını anlatmaya gerek yok, merak edenler Kotlin standard library kaynak kodlarına bakabilirler. Bu metodların developer’ların işini ne kadar kolaylaştırdığını göstermek için gerçek bir örnek vermek istiyorum.
Flickr çok eski bir fotoğraf paylaşım sitesi ve servislerini bir REST API üzerinden açıyor. Popüler resimleri sorgulamak için çağırılan bir servis aşağıdaki gibi bir json data dönüyor. (Çok fazla yer kaplamaması için json’ın bir kısmını kestim.)
{ "photos": { "page": 1, "pages": "3207", "perpage": 100, "total": "320662", "photo": [ { "id": "32547078274", "owner": "148578535@N03", "secret": "9f61ddcc9f", "server": "3855", "farm": 4, "title": "", "ispublic": 1, "isfriend": 0, "isfamily": 0 }, { "id": "33007015650", "owner": "148578535@N03", "secret": "9031056fa7", "server": "660", "farm": 1, "title": "", "ispublic": 1, "isfriend": 0, "isfamily": 0 }, .... { "id": "32547072484", "owner": "124285120@N06", "secret": "8f8de22696", "server": "3893", "farm": 4, "title": "Photo", "ispublic": 1, "isfriend": 0, "isfamily": 0 } ] }, "stat": "ok" }
Amacımız bu json’ı parse edip her foto için URL oluşturmak. Json işlemleri için ekstra bir kütüphane kullanmaya gerek yok. Android runtime içinde gelen org.json
kütüphanesi işimizi görür. Kotlin ve Java’nın bir kardeş gibi anlaştıklarından (Interoperability) ve Kotlin kodu içinden java ile yazılmış kütüphaneleri pürüzsüz bir şekilde kullabildiğimizden daha önceki yazılarda bahsetmiştim
JSONArray sınıfı çok primitive bir sınıf. Elemanlarını dolaşmak için bir iterator
sunmuyor. İlk yapacağımız iş JSONArray için bir iterator extension metodu yazmak olacak:
Artık JSONArray elemanlarını forEach
ile gezebiliriz:
Fakat map
ve filter
gibi extension’lar Iterable<T>
tipi üzerine tanımlandığı için bize JSONArray’ı Iterable’a dönüştürecek bir extension lazım:
Son vuruşu map
fonksiyonu ile yapıyoruz. map
sayesinde JSONObject’leri url string’lere dönüştüreceğiz.
Java’da olmayan bir başka Kotlin güzelliği de url string’i oluştururken kullandığımız string interpolation
yöntemi.
Ve sonuç olarak populer fotoların linklerine ulaşmış oluyoruz.
https://farm4.staticflickr.com/3855/32547078274_dcc9f61d9f.jpg https://farm1.staticflickr.com/660/33007015650_10a9056f37.jpg https://farm4.staticflickr.com/3895/33262233881_5a583dd624.jpg https://farm4.staticflickr.com/3948/32547078094_e751d10e40.jpg ...
Bir sonraki yazida Sequence‘lardan yani lazy
collection’lardan bahsedeceğim.