Understanding collections in Kotlin

Kotlin’s approach to storing values in containers is quite similar to the one found in Java. There are some important differences and nuances between the two, however, which are important to realise. It is also really handy to get used to idiomatic use of Kotlin’s standard library as it greatly enhances the experience.

Mutability

To me, the greatest feature concerning collections in Kotlin is the inherent immutability of collections. In Java and most other languages, collections default to being mutable – you modify them at runtime. Of course it is useful but it leads to a lot of bugs, e.g. when misunderstanding of in-place vs copy operations causes accidental updates to a list.

Kotlin fights this issue by essentially making every list, set, map and whatnot immutable by design. Actually every collection has its counterpart mutable class. For List, there is the MutableList, same stands true for Set and Map. This has an added effect of you having to explicitly state that you want the collection to be mutable which makes you think about if you need it or not.

Collection creation shorthands

One of the biggest weaknesses of Java is its verbosity. Creating a list in Java might look similar to this:

ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);

Kotlin’s equivalent would be:

val list = listOf(1,2,3,4)

As you can see, it is much shorter, more readable and safer as both the list reference and the list itself are both immutable. Type inference makes the explicit type declaration redundant and we are left with a beautiful, concise idiom for list creation.

Of course same idiom holds for MutableList, Sets and even Maps. Using mutableListOf(), setOf(), and mutableSetOf() is self-explanatory. However mapOf() and mutableMapOf() use one trick worth mentioning. The following idiom is not the fastest way to create a map but it is really handy to know.

val scoring = mapOf(
"horse" to 0,
"cat" to 5,
"dog" to 10,
"android" to 100
)

mapOf() function takes a varargs parameters of type Pair and puts them in a map as key/value pairs. “horse”.to(0) is a function call that returns a Pair(“horse”, 0). The to() function being marked as infix allows us to write it as seen above. This makes for a really natural looking code.

Basic functional operations

Using for loop for every collection operation is totally acceptable but a much better idea is to make us of some functional magic that Kotlin grants us with. Great lambda syntax and a great toolbox of inbuilt collection methods decrease the hassle of searching, filtering, modifying and sorting collections.

Initially I wanted to go through all of the amazing methods but I found a great article that already did it so I deemed it unnecessary and will instead link to it. I would love, however, to attract your attention to some really often used methods that you have to know.

Please pay close attention and try to use following methods explained in the link below:

forEach, forEachIndexed – execute the lambda function for every element in the collection
filter, filterNot – apply a predicate function to all elements and build a new collection with only those of them that returned either true or false.
map, mapIndexed, mapNotNull – apply a given function to every element and build a new collection with the results
sortBy – sorts the collection by values returned from calling the function provided

Kotlin also ships with two amazing methods that were quite a hassle to use in Java: zip and partition. They allow you to transform two collections into one and vice versa using a provided function. The details of usage of all those methods can be found in the post by Antonio Leiva who did much better job at it than I could ever hope for.

Antonio Leiva’s great article on the collection operations in Kotlin

Note that the article is a bit outdated as “merge” method is not available in Kotlin after Kotlin 1.0b2. Feel free to use .zip() instead. Thanks to Wojtek Okoński for pointing it out

Blog update

I am done with my writer’s break I took after GN’17 and this post is the one of many I’m planning to release in the near future. In a week’s time a post of mine will be featured on Applover’s blog. I will link to it when it’s up.

Leave a comment

Your email address will not be published. Required fields are marked *