Kotlin Temelleri-5

Armagan Civelek
6 min readJan 19, 2021

--

Road Map

1.BASİC

2.CONTROL FLOW

3.FUNCTİONS

4.KOTLİN OOP

5.COLLECTİONS

  • Collection Overview
  • List
  • Set
  • Map
  • Constructing Collections
  • Iterators

6.EXCEPTİON HANDLİNG

5) COLLECTIONS

A) Collection Overview

Bu bölümde, Kotlin Collection’ lar ile çalışmayı öğrenecek, verileri dönüştürecek, filtreleyecek ve farklı koleksiyon türleri ile çalışmayı öğreneceğiz.

Nedir ?

İçerisinde verileri saklayabildiğimiz , farklı koşullara göre filtreleyip gruplandırabildiğimiz kısacası verileri manipüle edip organize ettiğimiz bir yapıdır.

Neye göre ayırt ederiz ?

  • Hafıza kullanımı dinamik mi yoksa statik mi ?
  • Yinelenen elemanlara izin var mı?
  • Veri manipülasyonunda ne kadar hızlı ?
  • İçeriği değiştirilebilir mi?

Yukarıda ki soruların cevabını aşağıdaki tipleri öğrenerek bulacağız.

  • List
  • Set
  • Map

B) List

Listeler, dizilerin dinamik versiyonudur. Dinamik hafıza kelime anlamı olarak; listede ki her elemanı hafızada boş bulduğunuz herhangi bir yere yerleştirebildiğiniz manasına gelir. Listeler mutable ve immutable olabilirler.

Liste oluşturma →

fun main() {
val list = listOf(2, 3, 5, 6, 7)
println(list)
}
output:
[2, 3, 5, 6, 7]

Yukarıdaki kod bloğunda listOf() fonksiyonu ile 5 elemanlı bir liste oluşturuldu ve ekrana yazdırıldı.

Eğer bu kullanımı bir dizi ile yapmış olsaydık →

val array= arrayOf(1,2,3,4,5)
println(array)
output:
[Ljava.lang.Integer;@f6f4d33

Yukarıdaki gibi referans değerini dönen bir dizi bize anlamsız gelen harfler topluluğu görecektik.

!! Listelerde bunu görmememizin sebebi ise tüm koleksiyonların toString() methodunu override etmesidir.

Aşağıda ki kod parçasını çalıştırmaya kalktığımızda ise bir hata ile karşı karşıya kalırız. Bunun sebebi ise; list ve mutableList arasında ki farktan kaynaklanır.

fun main() {
val list = listOf(2, 3, 5, 6, 7)
list[3] = 100
}

Kotlin collection’ ların içeriğini ve boyutunu değiştirebilmemiz için muhakkak mutable ile başlaması gerekir.

Mutable List:

Veriyi manipüle etmek istersek MutableList oluşturmamız gerekir.

fun main() {
val numbers = mutableListOf(1, 2, 3, 4)
numbers.add(5)
numbers.removeAt(1)
numbers[0] = 0
numbers.shuffle()
println(numbers)
}

Peki ya bir değerin yinelenmesini istemiyorsak ?

2) Set

  • Set içerdiği değerler bakımından diğer collection türlerinden ayrılır.
  • Her elemanı eşsizdir ve tekrar etmez.
  • Id gibi eşsiz değerler tutarken kullanışlı bir yapı olacaktır.
  • Set, null değer içerebilir keza null da eşşiz bir değerdir.
  • Lakin birden fazla null değer içeremez.
  • Set yapısı tekrar eden değerleri belirleyebilmek için bünyesinde bulunan hashcode( ) fonksiyonunu kullanır.
data class Worker(
val id: Int,
val name: String
)

fun main() {
val workers = setOf(
Worker(id = 5, name = "Armağan"),
Worker(id = 3, name = "Emirhan"),
Worker(id = 5, name = "Armağan"),
Worker(id = 4, name = "Salih")
)

println(workers)
}
output:
[Worker(id=5, name=Armağan), Worker(id=3, name=Emirhan), Worker(id=4, name=Salih)]

Set’in ilk değer atamasını yaparken içerisine 4 eleman koysak da çıktısında 3 adet eleman görürüz. Bunun sebebi ise id ve name değeri tekrar eden iki eleman vardır.

Verilere erişim söz konusu olduğunda set kullanımı listelerden biraz daha farklıdır ;

  • Set yapısında bir veriyi indisi ile aramayız.
  • Çünkü bir itemin indisi o itemin hash kodudur.
  • Hash kodu biliyorsak zaten veriyi biliyoruzdur.
  • İndisleri olmadğı için sırasız koleksiyon olarak kabul edilirler.
  • Hangi sırayla veri eklendiği önemli değildir, yalnızca benzersiz veri tutmakla ilgilenirler.
data class Worker(
val id: Int,
val name: String
)

fun main() {
val workers = mutableSetOf(
Worker(id = 5, name = "Armağan"),
Worker(id = 3, name = "Emirhan"),
Worker(id = 5, name = "Armağan"),
Worker(id = 4, name = "Armağan")
)
println(workers)
val removedWorker = Worker(id = 5, name = "Armağan")
workers.remove(removedWorker)
println(workers)
output:
[Worker(id=5, name=Armağan), Worker(id=3, name=Emirhan), Worker(id=4, name=Armağan)]
[Worker(id=3, name=Emirhan), Worker(id=4, name=Armağan)]
}

3) Map

  • Collection arayüzünü implement etmemesine rağmen yine de collection olarak sınıflandırılır.
  • Tüm koleksiyonlar gibi map koleksiyonunun oluşturulması da kolay ve neredeyse aynıdır.
  • mapOf( ) fonksiyonu kullanarak bir map koleksiyonu oluşturabiliriz.
  • key value şeklinde verileri tutar.
  • Set collection’ da olduğu gibi tuttuğu key value çifti bakımından tekrarsızdır.
fun main() {
val httpHeaders = mapOf(
"Authorization" to "your-api-key",
"ContentType" to "application/json",
"UserLocale" to "US",
"UserLocale" to "US"
)

println(httpHeaders)
}
output:
{Authorization=your-api-key, ContentType=application/json, UserLocale=US}

MutableMap:

  • Bir mutablemap’e ekleme yapacağınız zaman add( ) fonksiyonu kullanamayız.
  • Bunun yerine put( ) fonksiyonunu kullanmamız gerekir.
fun main() {
val httpHeaders = mutableMapOf<String, String>(
"Authorization" to "your-api-key",
"ContentType" to "application/json",
"UserLocale" to "US",
"UserLocale" to "US"
)



httpHeaders.put("default-search", "www.google.com.tr")
println(httpHeaders.get("default-search"))

}
output:
www.google.com.tr
  • Ayrıca şu iki kullanımda aynı işi görür.
httpHeaders.put("Hello", "World") // aynı çıktıya sahip oluruz.

httpHeaders["Hello"] = "World"
  • Map collection’lar içerisinde dolaşmak diğer collection tiplerine göre biraz farklıdır.
  • Her iterasyonda key,value çiftini bilmemiz gerektiğinden, iki değere de sahip olurusunuz.
httpHeaders.forEach { key, value -> println("Value for key $key is $value") }

4) Constructing Collections

Kotlinde, bir collection oluşturmanın en yaygın yolu standart kütüphane fonksiyonları olan →

  • setOf<T>( )
  • listOf<T>( )
  • mutableListOf<T>( ) ….

ki bundan önce ki tüm örneklerimizde bu yolu izledik.

Map nesnelerini oluştururken de bu standart kütüphane fonksiyonlarından yararlandık.

val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 1)

Kotlin dökümantasyonlarında yukardda ki kullanımın sadece performansın kritik olmadığı uygulamalarda kullanılmasının uygun olduğu söyleniyor. Aşırı hafıza kullanımını engellemek için ise alternatif bir yol sunuyor.

val numbersMap = mutableMapOf<String, String>().apply { this["one"] = "1"; this["two"] = "2" }

Empty Collection:

Şimdiye kadar oluşturduğumuz tüm collection tiplerinde ilk değer atamalarını yaptık. Fakat boş bir collection da oluşturmamıza imkan verilir.

val empty = emptyList<String>()

Listelere değer atama :

Listeler için ilk değer atamanın şöyle kolay bir yolu daha mevcuttur.

fun main() {
val doubled = List(3, { it * 2 })
println(doubled)
}

Eğer içeriği sonradan değiştirmek istersek List yetine MutableList kullanılabilir.

Kopyalama:

Mevcut bir koleksiyonla aynı öğelere sahip bir koleksiyon oluşturmak için kopyalama işlemlerini kullanabilirsiniz.

  • toLıist( )
  • toMutableList( )
  • toSet( )
fun main() {
val sourceList = mutableListOf(1, 2, 3)
val copyList = sourceList.toMutableList()
val readOnlyCopyList = sourceList.toList()
sourceList.add(4)
println("Copy size: ${copyList.size}")

//readOnlyCopyList.add(4) // compilation error
println("Read-only copy size: ${readOnlyCopyList.size}")
println(sourceList.size)

}
output :
Copy size: 3
Read-only copy size: 3
4

PASS BY VALUE ve CALL BY REFERENCE

Bu fonksiyonlar, collection’ ları diğer türlere dönüştürmek için de kullanılabilir, örneğin, bir listeden bir set oluşturmak veya tam tersi

val sourceList = mutableListOf(1, 2, 3)    
val copySet = sourceList.toMutableSet()
copySet.add(3)
copySet.add(4)
println(copySet)

Ayrıca, aynı collection örneğine yeni referanslar oluşturabiliriz. Ne demek istiyoruz ?

  • Yukarıda yaptığımız kopyalama işlemlerinin hepsinde collection’ın hafızadaki adresi yerine değerlerini kopyalıyorduk.
  • Şimdi vereceğimiz örnekte ise collection itemlerinin birer kopyasını almak yerine hafızadaki adresini birebir yeni collection tipine atamış olucaz .
val sourceList = mutableListOf(1, 2, 3)
val referenceList = sourceList
referenceList.add(4)
println("Source size: ${sourceList.size}")
output:
Source size: 4

Yukarıda ki kod parçasında →

  • sourceList adında bir mutableList oluşturuldu
  • sourceList referansı yeni oluşturulan refenceList adlı değişkene atandı.
  • referenceList adlı collection’ a 4 tam sayı değeri eklendi.
  • Ekrana başta 3 elemanlı sourceList adlı değişkenin boyutu yazdırıldığında ise 4 çıktısını gördük.
  • Bunun sebebi açıkca anlaşılacağı üzere: referenceList ve sourceList adlı collection değişkenlerinin hafızada aynı adresi tutmalarıdır.

6)Iterators

Koleksiyon öğelerini dolaşmak için, kotlin standart kitaplığı, öğelere sırayla erişim sağlayan nesneler olan ıterator’ları yaygın olarak kullanılan mekanizmasını destekler. Iterator’ler , bir koleksiyonun tüm öğelerini tek tek işlemeniz gerektiğinde, örneğin değerleri yazdırmanız veya bunlara benzer güncellemeler yapmanız gerektiğinde kullanışlıdır.

fun main() {

val numbers = listOf("one", "two", "three", "four")
val numbersIterator = numbers.iterator()
while (numbersIterator.hasNext()) {
println(numbersIterator.next())
}
}
output:
one
two
three
four

next( ) fonksiyonu ögeyi geri döndürür ve varsa iterator konumunu bir sonraki ögeye taşır.

Collection içerisinde dolaşmanın bir diğer yolu da çok iyi bilinen for döngüsüdür.

val numbers = listOf("one", "two", "three", "four")
for (item in numbers) {
println(item)
}
output :
one
two
three
four

Ve tabi ki forEach( )

val numbers = listOf("one", "two", "three", "four")
numbers.forEach {
println(it)
}
output:
one
two
three
four

List iterator:

Listeler için bir özel gezinme şeklimiz daha mevcuttur. Listede ileri ve geri dolaşmamıza olanak sağlar.

val numbers = listOf("one", "two", "three", "four")
val listIterator = numbers.listIterator()
while (listIterator.hasNext()) listIterator.next()
println("Iterating backwards:")
while (listIterator.hasPrevious()) {
print("Index: ${listIterator.previousIndex()}")
println(", value: ${listIterator.previous()}")
}

Bu kullanım bize son ögeye ulaşsak bile geriye dönebilme imkanı sunar.

Kotlin temelleri altıncı kısım için tıklayınız..

--

--