Kotlin Collections
Hello!
Android Engineer @LyrebirdStudio
I am here because I love share everything I know.
You can find me at @ozcandroid
2
I am Halil ÖZCAN
“I will, in fact, claim that the difference
between a bad programmer and a good
one is whether he considers his code or
his data structures more important.
Bad programmers worry about the
code.
Good programmers worry about data
structures and their relationships.”
3
“
4
A collection is a structure which
usually contains numbers of objects
(this number may be zero) that of
the same type. Objects in a
collection called element or items.
What are Collections?
◎ A read-only interface that
provides operations for
accessing collection elements.
◎ A mutable interface that
extends the corresponding
read-only interface with write
operations : removing, adding,
updating... 5
Collection Type Interfaces
◎ List: ordered collection with access
to elements by indices. Elements
can occur more than once. (Group
of words)
◎ Set: collection of unique elements
(a group of objects without
repetitions). (Alphabet)
6
Collection Types
◎ Map: set of key value pair. Keys are
unique and each of them points to
exactly one value. Use for storing
logical connection. Students’ ID
and their class.
7
Collection Types
8
9
10
Let’s Play With
Lists
11
val kotlinLanguage = "Kotlin"
val eventWordList =
listOf("Kotlin","Everywhere","is","a","great","event")
eventWordList.get(0) // Not Recommended
eventWordList[0] // getting element with index
eventWordList.indexOf(kotlinLanguage) // getting index of
element
eventWordList.shuffled() // Doesn't effect original collection
12
val kotlinLanguage = "Kotlin"
val eventWordList =
mutableListOf("Kotlin","Everywhere","is","a","great",
"event")
eventWordList.set(0,"Java :(") // Not Recommended :)
eventWordList[0] = kotlinLanguage // Updating with index
eventWordList.removeAt(0) // Deleting with index
val exclamationMark = "!"
val eventWordList =
listOf("Kotlin","Everywhere","is","a","great","event","!")
val removedWithElement = eventWordList - exclamationMark // remove first
occurrence
// [Kotlin, Everywhere, is, a, great, event]
val removedWithList = eventWordList - listOf("is","a") // remove all
occurrences
// [Kotlin, Everywhere, great, event, !]
val addedList = eventWordList + "Let's fun with it!"
// [Kotlin, Everywhere, is, a, great, event, !, Let's fun with it!]
val names = listOf("Halil", "Murat", "Elif", "Okan")
names.first() // Halil
names.last() // Okan
names.elementAt(2) // Elif
names.elementAtOrNull(4) // prevent
IndexOutOfBoundException - returns null
names.elementAtOrElse(4) {
// Do something because of index not found
}
val names = listOf("Halil", "Murat","Kağan", "Elif", "Okan")
names.first {
it.contains("t")
} // Murat
names.last {
it.contains("f")
} // Elif
names.firstOrNull { // You can use also find() alias
it.startsWith("z")
} // Null
names.lastOrNull { //You can use also findLast() alias
it.endsWith("n")
} // Okan
val languages = listOf("Kotlin", "Java", "C", "PHP",
"Javascript")
languages.filter { // Doesn't effect original collection
it.length > 4
}.forEach {
println(it)
}
val filteredLanguages = mutableListOf<String>()
languages.filterTo(filteredLanguages) {
it.length > 4
}
languages.filterIndexedTo(filteredLanguages){ index, _ ->
index == 3
} // filteredLanguages [Kotlin, Javascript, PHP]
18
val complexList =
listOf(null,"Kotlin",1967,null,true)
complexList.filterIsInstance<String>() // Kotlin
complexList.filterNotNull() // [Kotlin, 1967, true]
complexList.filterNot { it == null }
// [Kotlin, 1967, true]
19
Partitioning List
&
Sublisting
val kotlinLanguage = "Kotlin"
val languages = listOf("Kotlin", "Java", "C", "PHP",
"Javascript")
val(match,rest) = languages.partition {
it == kotlinLanguage
}
// match [Kotlin]
// rest [Java, C, PHP, Javascript]
val subLanguages = languages.subList(1,languages.size-1)
// [Java, C, PHP, Javascript]
21
Take & Drop
val eventWordList = listOf("Kotlin", "Everywhere", "is", "a",
"great", "event", "!")
eventWordList.take(4) // [Kotlin, Everywhere, is, a]
eventWordList.takeLast(5) // [is, a, great, event, !]
eventWordList.drop(1) // [Everywhere, is, a, great, event, !]
eventWordList.dropLast(5) // [Kotlin, Everywhere]
val eventWordList = listOf("Kotlin", "Everywhere", "is", "a",
"great", "event", "!")
eventWordList.takeWhile { !it.startsWith("a") }
// [Kotlin, Everywhere, is]
eventWordList.takeLastWhile { it != "Kotlin" }
// [Everywhere, is, a, great, event, !]
eventWordList.dropWhile { !it.startsWith("a") }
// [a, great, event, !]
eventWordList.dropLastWhile { !it.startsWith("E") }
// [Kotlin, Everywhere]
24
Chunked
val numbers = (1..10).toList()
numbers.chunked(3)
// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
numbers.chunked(3){
it.sum()
}
// [6, 15, 24, 10]
26
Windowed
val numbers = (1..5).toList()
numbers.windowed(3)
// [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
numbers.windowed(3, step = 2, partialWindows = true)
// [[1, 2, 3], [3, 4, 5], [5]]
numbers.windowed(3) {
it.sum()
}
// [6, 9, 12]
28
Folds & Reduce
val eventWordList = listOf("Kotlin ", "Everywhere ", "is ", "a
", "great ", "event", "!")
eventWordList.reduce { sentence, element ->
sentence + element
}
// Kotlin Everywhere is a great event!
eventWordList.fold("") { sentence, element ->
sentence + element
}
// Kotlin Everywhere is a great event!
any()
returns true if at
least one element
matches the
given predicate.
none()
returns true if
none of the
elements match
the given
predicate.
all()
returns true if all
elements match
the given
predicate. Note
that all()
returns true when
called with any
valid predicate on
an empty
collection
30
Testing Predicates
val eventSuccessWord = "great"
val eventFailWord = "bad"
val eventWordList =
listOf("Kotlin","Everywhere","is","a","great","event")
eventWordList.any { it == eventSuccessWord } // Event is
success
eventWordList.none { it == eventFailWord } // Event is success
eventWordList.all { it != eventFailWord} // Event is success
emptyList<String>().all { it.length>5 } // True
32
Let’s Play With
Sets
var tvSeries = mutableSetOf("Breaking Bad","How I Met Your
Mother?","Lost")
tvSeries = (tvSeries union setOf("Game Of
Thrones","Lost")).toMutableSet()
// Lost is not added again
// [Breaking Bad, How I Met Your Mother?, Lost, Game Of
Thrones]
val badFinals = mutableSetOf("Game Of Thrones","Lost")
tvSeries = (tvSeries - badFinals) as MutableSet<String>
// [Breaking Bad, How I Met Your Mother?]
val numberSet = listOf(
setOf(1, 2, 3), setOf(4, 5, 6), setOf(7, 8, 9))
numberSet.first().first() // 1
numberSet.first().last() // 3
numberSet.last().first() // 7
numberSet.last().last() // 9
val numbers = setOf(1, 2, 3, 4, 5)
numbers intersect setOf(1, 2)
// [1, 2]
numbers subtract setOf(4, 5)
// [1, 2, 3]
numbers subtract setOf(5, 4)
// [1, 2, 3]
36
Let’s Play With
Maps
val cityMap = mapOf(34 to "İstanbul",
6 to "Ankara", 61 to "Trabzon")
cityMap.get(34)
// get with function - Not Recommended
cityMap[34] // get with index
cityMap.keys // get all keys
cityMap.values // get all values
val cityMap = mutableMapOf(34 to "İstanbul", 6 to "Ankara", 61 to
"Trabzon")
cityMap.put(16, "Bursa") // put with function - not recommended
cityMap[35] = "İzmir" // put-update with index
cityMap.remove(34) // delete
cityMap.getOrPut(28,{
"Giresun"
})
// if there is a value with key 28, get it otherwise put the value
with key 28
// {6=Ankara, 61=Trabzon, 16=Bursa, 35=İzmir, 28=Giresun}
cityMap.getOrDefault(34,"Not Found!")
val cityMap = mutableMapOf(34 to "İstanbul", 6 to "Ankara", 61 to "Trabzon")
// Also there are filterKeys and filterValues functions
println(cityMap.filter { (key, value) ->
key >= 34 && value.length > 5
})
// {34=İstanbul, 61=Trabzon}
cityMap + Pair(16, "Bursa") // {34=İstanbul, 6=Ankara, 61=Trabzon, 16=Bursa}
cityMap + mapOf(28 to "Giresun") // {34=İstanbul, 6=Ankara, 61=Trabzon,
28=Giresun}
cityMap - listOf(61) // {34=İstanbul, 6=Ankara}
41
42
Sequences
val sequence = sequenceOf(1, 2, 3, 4)
// You can use all iterable functions with sequences
listOf(1, 2, 3, 4).asSequence() // from iterable collection
generateSequence(1) {
it + 1
} // infinite sequence
generateSequence(1) {
if (it < 10) it else null
} // finite sequence
val evenNumbers = sequence {
// suspend until next element requested by consumer
yield(0) // return element to sequence consumer
yieldAll(listOf(2, 4)) // can take any Iterable or Sequence
yieldAll(generateSequence(6) {
it + 2
})
// infinite call
// - it must be last -
// all subsequent calls will never be executed
}
evenNumbers.take(5).toList()
// [0, 2, 4, 6, 8]
Iterable vs Sequences
● Sequences offer the
same functions as
Iterable but implement
another approach to
multi-step collection
processing.
● When the processing of an
Iterable each process step
completes and returns its
result – an intermediate
collection. In turn, multi-
step processing of
sequences is executed lazily
when possible
45
Iterable vs Sequences
● The order of operations execution is different
as well: Sequence performs all the processing
steps one-by-one for every single element. In
turn, Iterable completes each step for the whole
collection and then proceeds to the next step.
46
val eventWordList = "Kotlin Everywhere is a
great event".split(" ")
eventWordList.filter {
it.length > 5
}.map {
it.toUpperCase()
}.take(4)
// [KOTLIN, EVERYWHERE]
12 Steps 😒
val eventWordList = "Kotlin Everywhere is a great
event".split(" ")
val eventWordsSequence = eventWordList.asSequence()
eventWordsSequence.filter {
it.length > 5
}.map {
it.toUpperCase()
}.take(2)
// [KOTLIN, EVERYWHERE]
8 Steps 😉
51
Collection Transformations
52
Mapping
val cities = listOf("İstanbul", "Ankara", "Trabzon")
val citiesMap = mapOf(34 to "İstanbul", 6 to "Ankara", 61 to
"Trabzon")
cities.map { it.toUpperCase() }
// [İSTANBUL, ANKARA, TRABZON]
cities.mapIndexed { index, element ->
index + element.length
} // [8, 7, 9]
citiesMap.mapKeys { it.key * 2 }
//{68=İstanbul, 12=Ankara, 122=Trabzon}
citiesMap.mapValues { it.key + it.value.length }
//{34=42, 6=12, 61=68}
54
Zipping
val foundedYears = listOf(1975, 1976, 1998)
val companies = listOf("Microsoft", "Apple", "Google")
companies.zip(foundedYears) { company, foundedYear ->
"$company - $foundedYear"
}
// [Microsoft - 1975, Apple - 1976, Google - 1998]
val companyPairs = listOf(1975 to "Microsoft", 1976 to
"Apple", 1998 to "Google")
companyPairs.unzip()
//([1975, 1976, 1998], [Microsoft, Apple, Google])
56
Association
val names = listOf("Halil", "Murat", "Elif", "Okan")
println(names.associateWith {
it.length
})
// {Halil=5, Murat=5, Elif=4, Okan=4}
println(names.associateBy(keySelector = {
it.toLowerCase()
}, valueTransform = {
it.length
}))
// {Halil=5, Murat=5, Elif=4, Okan=4}
Thanks!
Any questions?
You can find me at @ozcandroid & mail@halilozcan.com
58

Kotlin Collections

  • 1.
  • 2.
    Hello! Android Engineer @LyrebirdStudio Iam here because I love share everything I know. You can find me at @ozcandroid 2 I am Halil ÖZCAN
  • 3.
    “I will, infact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers worry about the code. Good programmers worry about data structures and their relationships.” 3
  • 4.
    “ 4 A collection isa structure which usually contains numbers of objects (this number may be zero) that of the same type. Objects in a collection called element or items. What are Collections?
  • 5.
    ◎ A read-onlyinterface that provides operations for accessing collection elements. ◎ A mutable interface that extends the corresponding read-only interface with write operations : removing, adding, updating... 5 Collection Type Interfaces
  • 6.
    ◎ List: orderedcollection with access to elements by indices. Elements can occur more than once. (Group of words) ◎ Set: collection of unique elements (a group of objects without repetitions). (Alphabet) 6 Collection Types
  • 7.
    ◎ Map: setof key value pair. Keys are unique and each of them points to exactly one value. Use for storing logical connection. Students’ ID and their class. 7 Collection Types
  • 8.
  • 9.
  • 10.
  • 11.
    11 val kotlinLanguage ="Kotlin" val eventWordList = listOf("Kotlin","Everywhere","is","a","great","event") eventWordList.get(0) // Not Recommended eventWordList[0] // getting element with index eventWordList.indexOf(kotlinLanguage) // getting index of element eventWordList.shuffled() // Doesn't effect original collection
  • 12.
    12 val kotlinLanguage ="Kotlin" val eventWordList = mutableListOf("Kotlin","Everywhere","is","a","great", "event") eventWordList.set(0,"Java :(") // Not Recommended :) eventWordList[0] = kotlinLanguage // Updating with index eventWordList.removeAt(0) // Deleting with index
  • 13.
    val exclamationMark ="!" val eventWordList = listOf("Kotlin","Everywhere","is","a","great","event","!") val removedWithElement = eventWordList - exclamationMark // remove first occurrence // [Kotlin, Everywhere, is, a, great, event] val removedWithList = eventWordList - listOf("is","a") // remove all occurrences // [Kotlin, Everywhere, great, event, !] val addedList = eventWordList + "Let's fun with it!" // [Kotlin, Everywhere, is, a, great, event, !, Let's fun with it!]
  • 14.
    val names =listOf("Halil", "Murat", "Elif", "Okan") names.first() // Halil names.last() // Okan names.elementAt(2) // Elif names.elementAtOrNull(4) // prevent IndexOutOfBoundException - returns null names.elementAtOrElse(4) { // Do something because of index not found }
  • 15.
    val names =listOf("Halil", "Murat","Kağan", "Elif", "Okan") names.first { it.contains("t") } // Murat names.last { it.contains("f") } // Elif names.firstOrNull { // You can use also find() alias it.startsWith("z") } // Null names.lastOrNull { //You can use also findLast() alias it.endsWith("n") } // Okan
  • 17.
    val languages =listOf("Kotlin", "Java", "C", "PHP", "Javascript") languages.filter { // Doesn't effect original collection it.length > 4 }.forEach { println(it) } val filteredLanguages = mutableListOf<String>() languages.filterTo(filteredLanguages) { it.length > 4 } languages.filterIndexedTo(filteredLanguages){ index, _ -> index == 3 } // filteredLanguages [Kotlin, Javascript, PHP]
  • 18.
    18 val complexList = listOf(null,"Kotlin",1967,null,true) complexList.filterIsInstance<String>()// Kotlin complexList.filterNotNull() // [Kotlin, 1967, true] complexList.filterNot { it == null } // [Kotlin, 1967, true]
  • 19.
  • 20.
    val kotlinLanguage ="Kotlin" val languages = listOf("Kotlin", "Java", "C", "PHP", "Javascript") val(match,rest) = languages.partition { it == kotlinLanguage } // match [Kotlin] // rest [Java, C, PHP, Javascript] val subLanguages = languages.subList(1,languages.size-1) // [Java, C, PHP, Javascript]
  • 21.
  • 22.
    val eventWordList =listOf("Kotlin", "Everywhere", "is", "a", "great", "event", "!") eventWordList.take(4) // [Kotlin, Everywhere, is, a] eventWordList.takeLast(5) // [is, a, great, event, !] eventWordList.drop(1) // [Everywhere, is, a, great, event, !] eventWordList.dropLast(5) // [Kotlin, Everywhere]
  • 23.
    val eventWordList =listOf("Kotlin", "Everywhere", "is", "a", "great", "event", "!") eventWordList.takeWhile { !it.startsWith("a") } // [Kotlin, Everywhere, is] eventWordList.takeLastWhile { it != "Kotlin" } // [Everywhere, is, a, great, event, !] eventWordList.dropWhile { !it.startsWith("a") } // [a, great, event, !] eventWordList.dropLastWhile { !it.startsWith("E") } // [Kotlin, Everywhere]
  • 24.
  • 25.
    val numbers =(1..10).toList() numbers.chunked(3) // [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] numbers.chunked(3){ it.sum() } // [6, 15, 24, 10]
  • 26.
  • 27.
    val numbers =(1..5).toList() numbers.windowed(3) // [[1, 2, 3], [2, 3, 4], [3, 4, 5]] numbers.windowed(3, step = 2, partialWindows = true) // [[1, 2, 3], [3, 4, 5], [5]] numbers.windowed(3) { it.sum() } // [6, 9, 12]
  • 28.
  • 29.
    val eventWordList =listOf("Kotlin ", "Everywhere ", "is ", "a ", "great ", "event", "!") eventWordList.reduce { sentence, element -> sentence + element } // Kotlin Everywhere is a great event! eventWordList.fold("") { sentence, element -> sentence + element } // Kotlin Everywhere is a great event!
  • 30.
    any() returns true ifat least one element matches the given predicate. none() returns true if none of the elements match the given predicate. all() returns true if all elements match the given predicate. Note that all() returns true when called with any valid predicate on an empty collection 30 Testing Predicates
  • 31.
    val eventSuccessWord ="great" val eventFailWord = "bad" val eventWordList = listOf("Kotlin","Everywhere","is","a","great","event") eventWordList.any { it == eventSuccessWord } // Event is success eventWordList.none { it == eventFailWord } // Event is success eventWordList.all { it != eventFailWord} // Event is success emptyList<String>().all { it.length>5 } // True
  • 32.
  • 33.
    var tvSeries =mutableSetOf("Breaking Bad","How I Met Your Mother?","Lost") tvSeries = (tvSeries union setOf("Game Of Thrones","Lost")).toMutableSet() // Lost is not added again // [Breaking Bad, How I Met Your Mother?, Lost, Game Of Thrones] val badFinals = mutableSetOf("Game Of Thrones","Lost") tvSeries = (tvSeries - badFinals) as MutableSet<String> // [Breaking Bad, How I Met Your Mother?]
  • 34.
    val numberSet =listOf( setOf(1, 2, 3), setOf(4, 5, 6), setOf(7, 8, 9)) numberSet.first().first() // 1 numberSet.first().last() // 3 numberSet.last().first() // 7 numberSet.last().last() // 9
  • 35.
    val numbers =setOf(1, 2, 3, 4, 5) numbers intersect setOf(1, 2) // [1, 2] numbers subtract setOf(4, 5) // [1, 2, 3] numbers subtract setOf(5, 4) // [1, 2, 3]
  • 36.
  • 37.
    val cityMap =mapOf(34 to "İstanbul", 6 to "Ankara", 61 to "Trabzon") cityMap.get(34) // get with function - Not Recommended cityMap[34] // get with index cityMap.keys // get all keys cityMap.values // get all values
  • 38.
    val cityMap =mutableMapOf(34 to "İstanbul", 6 to "Ankara", 61 to "Trabzon") cityMap.put(16, "Bursa") // put with function - not recommended cityMap[35] = "İzmir" // put-update with index cityMap.remove(34) // delete cityMap.getOrPut(28,{ "Giresun" }) // if there is a value with key 28, get it otherwise put the value with key 28 // {6=Ankara, 61=Trabzon, 16=Bursa, 35=İzmir, 28=Giresun} cityMap.getOrDefault(34,"Not Found!")
  • 40.
    val cityMap =mutableMapOf(34 to "İstanbul", 6 to "Ankara", 61 to "Trabzon") // Also there are filterKeys and filterValues functions println(cityMap.filter { (key, value) -> key >= 34 && value.length > 5 }) // {34=İstanbul, 61=Trabzon} cityMap + Pair(16, "Bursa") // {34=İstanbul, 6=Ankara, 61=Trabzon, 16=Bursa} cityMap + mapOf(28 to "Giresun") // {34=İstanbul, 6=Ankara, 61=Trabzon, 28=Giresun} cityMap - listOf(61) // {34=İstanbul, 6=Ankara}
  • 41.
  • 42.
  • 43.
    val sequence =sequenceOf(1, 2, 3, 4) // You can use all iterable functions with sequences listOf(1, 2, 3, 4).asSequence() // from iterable collection generateSequence(1) { it + 1 } // infinite sequence generateSequence(1) { if (it < 10) it else null } // finite sequence
  • 44.
    val evenNumbers =sequence { // suspend until next element requested by consumer yield(0) // return element to sequence consumer yieldAll(listOf(2, 4)) // can take any Iterable or Sequence yieldAll(generateSequence(6) { it + 2 }) // infinite call // - it must be last - // all subsequent calls will never be executed } evenNumbers.take(5).toList() // [0, 2, 4, 6, 8]
  • 45.
    Iterable vs Sequences ●Sequences offer the same functions as Iterable but implement another approach to multi-step collection processing. ● When the processing of an Iterable each process step completes and returns its result – an intermediate collection. In turn, multi- step processing of sequences is executed lazily when possible 45
  • 46.
    Iterable vs Sequences ●The order of operations execution is different as well: Sequence performs all the processing steps one-by-one for every single element. In turn, Iterable completes each step for the whole collection and then proceeds to the next step. 46
  • 47.
    val eventWordList ="Kotlin Everywhere is a great event".split(" ") eventWordList.filter { it.length > 5 }.map { it.toUpperCase() }.take(4) // [KOTLIN, EVERYWHERE]
  • 48.
  • 49.
    val eventWordList ="Kotlin Everywhere is a great event".split(" ") val eventWordsSequence = eventWordList.asSequence() eventWordsSequence.filter { it.length > 5 }.map { it.toUpperCase() }.take(2) // [KOTLIN, EVERYWHERE]
  • 50.
  • 51.
  • 52.
  • 53.
    val cities =listOf("İstanbul", "Ankara", "Trabzon") val citiesMap = mapOf(34 to "İstanbul", 6 to "Ankara", 61 to "Trabzon") cities.map { it.toUpperCase() } // [İSTANBUL, ANKARA, TRABZON] cities.mapIndexed { index, element -> index + element.length } // [8, 7, 9] citiesMap.mapKeys { it.key * 2 } //{68=İstanbul, 12=Ankara, 122=Trabzon} citiesMap.mapValues { it.key + it.value.length } //{34=42, 6=12, 61=68}
  • 54.
  • 55.
    val foundedYears =listOf(1975, 1976, 1998) val companies = listOf("Microsoft", "Apple", "Google") companies.zip(foundedYears) { company, foundedYear -> "$company - $foundedYear" } // [Microsoft - 1975, Apple - 1976, Google - 1998] val companyPairs = listOf(1975 to "Microsoft", 1976 to "Apple", 1998 to "Google") companyPairs.unzip() //([1975, 1976, 1998], [Microsoft, Apple, Google])
  • 56.
  • 57.
    val names =listOf("Halil", "Murat", "Elif", "Okan") println(names.associateWith { it.length }) // {Halil=5, Murat=5, Elif=4, Okan=4} println(names.associateBy(keySelector = { it.toLowerCase() }, valueTransform = { it.length })) // {Halil=5, Murat=5, Elif=4, Okan=4}
  • 58.
    Thanks! Any questions? You canfind me at @ozcandroid & mail@halilozcan.com 58