Kotlin Collections: Getting Started
In this tutorial, you’ll learn how to work with Kotlin Collections. You’ll transform data, filter it out, and use different types of collections in Kotlin! By Filip Babić.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Kotlin Collections: Getting Started
30 mins
- Getting Started
- What are Collections?
- Collection Types
- Arrays in Kotlin
- Creating An Array
- Working With Arrays
- Lists in Kotlin
- Creating a List
- Mutable Lists
- Sets in Kotlin
- Creating Sets
- Working With Sets
- Maps in Kotlin
- Creating a Map
- Working With a Map
- Concrete Collection Types
- Collection Operators
- Transforming Data
- Filtering and Grouping Data
- Validating Data
- Looking Up Data
- Where To Go From Here
Lists in Kotlin
Lists are a dynamic version of arrays. In terms of memory, dynamic means that you can allocate each element in any free memory slot. Because of this, you can have very large lists of data since you can scatter elements around in memory.
List
collections can be both mutable and immutable in terms of their size and contents.
Lists are useful in programming. Since you’ll use lists in your everyday coding it’s important to understand them.
Once again, depending on your work environment, open the Lists.kt file or clear the Kotlin Playground code and add the following code:
fun main() {
val list = listOf(2, 3, 5, 6, 7)
println(list)
}
If you run the snippet above, you should see the numbers printed out. This is because all true collections override toString()
. Additionally, you can use the square brackets syntax to access the values.
Try to do the following:
fun main() {
val list = listOf(2, 3, 5, 6, 7)
list[2] = 100
}
You’ll receive an error. This is because there is a distinct difference between a List
and MutableList
construct in Kotlin collections.
You can change the size and contents of Kotlin collections which start with the Mutable
.
To be able to add, remove and insert elements at certain indices, you have to create a MutableList using mutableListOf()
. Take the following snippet for example:
fun main() {
val list = mutableListOf(2, 3, 5, 6, 7)
list[2] = 100 // works now
println(list[2]) // 100
list.add(index = 3, element = 500)
println(list[3]) // 500
list.remove(7)
println(list) // [2, 3, 100, 500, 6]
list.removeAt(0)
println(list) // [3, 100, 500, 6]
}
Because the list is now mutable, you can change items at indices, add items at specific indices and remove items at provided indices.
But what if you don’t want to have duplicate elements? You’d use Sets to eliminate duplicates and preserve elements uniqueness.
Sets in Kotlin
A set is a collection of elements where each of the elements is unique and there are no duplicates. They’re useful when you need to filter out duplicates. For example, you might use a set when storing ids or users.
Sets are a more advanced version of lists, with internal filtering of data. Like lists, they can be both mutable and immutable.
To create a set, use setOf()
or mutableSetOf()
. If you run the snippet, you’ll see only three items will print, even though there are four items in the set initializer function. This is because there are two items with the same id and name:
data class Worker(
val id: Int,
val name: String
)
fun main() {
val workers = setOf(
Worker(id = 5, name = "Filip"),
Worker(id = 3, name = "Mike"),
Worker(id = 5, name = "Filip"),
Worker(id = 4, name = "Filip")
)
// hashcode is used to remove duplicates
println(workers)
}
Sets use an object’s hashCode()
internally to filter out duplicates. If the set is mutable and you try to add another element to it, the new object will replace the old one. You can override hashCode()
and manually determine how to differentiate the elements.
Sets are a bit different than lists when it comes to accessing data. You wouldn’t look up items in a set using indices since the index of an item is actually it’s hash code. If you know the hash code, then you should already have the value.
As such, you’ll use sets to store data inside and keep a clear, unique, collection of elements. You can still iterate over them. Check the following code:
data class Worker(
val id: Int,
val name: String
)
fun main() {
val workers = mutableSetOf(
Worker(id = 5, name = "Filip"),
Worker(id = 3, name = "Mike"),
Worker(id = 5, name = "Filip"),
Worker(id = 4, name = "Filip")
)
println(workers) // [Worker(id=5, name=Filip), Worker(id=3, name=Mike), Worker(id=4, name=Filip)]
val removedWorker = Worker(id = 5, name = "Filip")
workers.remove(removedWorker)
println(workers) // [Worker(id=3, name=Mike), Worker(id=4, name=Filip)]
}
Since Sets do not have indices, they’re considered an unordered collection. Sets don’t care about what order you insert things in, they only care to store unique object instances. Sets are also used at the core of Maps collections.
Maps in Kotlin
Maps store pairs of objects where each value has a distinctive key. Each pair can be of any type you want and contains two objects.
Maps are collections of key/value pairs. As such, maps are extremely useful when you’re trying to tie one value to a key like an id or a String
identifier.
And like other collections, maps can be both mutable and immutable.
You can probably guess how to create a map by now, given that you initialize all the collections the same way. :]
fun main() {
val httpHeaders = mapOf(
"Authorization" to "your-api-key",
"ContentType" to "application/json",
"UserLocale" to "US")
}
By using mapOf()
you can create a map. Each map has two generic type parameters: key and value. In the initializer, you use to()
to create pairs of values with ease. Given that the pairs are of two strings, you’re creating a Map
of types String, String
.
As you can see, you’re creating an HTTP headers map for the authorization key, the content type format and the user’s locale. If you send this to a backend server, it can look at each of the keys and read the values paired with them.
And because maps use sets internally, by having key set all the keys are unique and there are no duplicates.
Like with sets and lists, maps are immutable by default. To create a mutable map, you have to use mutableMapOf()
:
fun main() {
val httpHeaders = mutableMapOf(
"Authorization" to "your-api-key",
"ContentType" to "application/json",
"UserLocale" to "US")
}
Now, you can change its values by their keys:
...
httpHeaders["Authorization"] = "something else"
println(httpHeaders["Authorization"]) // something else
Because the indices in a map are actually the keys, whichever type of key you use, you have to pass in the square brackets. Moreover, if you want to add values, you don’t add()
them, per se. Instead, you have to call put()
, like below:
...
httpHeaders.put("Hello", "World")
println(httpHeaders) // {Authorization=something else, ContentType=application/json, UserLocale=US, Hello=World}
or
...
httpHeaders["Hello"] = "World"
println(httpHeaders) // {Authorization=something else, ContentType=application/json, UserLocale=US, Hello=World}
This is the same as using the assignment operator with the appropriate key.
Iterating through maps is a bit different from the rest of Kotlin collections. Since maps have two objects for each element, you have to iterate over pairs, instead of single values. You can do this in the following way:
httpHeaders.forEach { key, value -> println("Value for key $key is $value") }
You iterate through the pairs. In each iteration, you receive both the key and the value for that key, since it’s often necessary to know and consume both the key and the value.
Nice work! Kotlin collections provide much more functionality for data consuming and transforming.