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:
Kotlin’s equivalent would be:
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.
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.
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
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.