Kotlin Mutable and Immutable Collections

In this article I would like to emphasise over a few options that we have when working with data structure and more precisely with collections in a mutable and immutable fashion. So let’s start with a few of them and see their mutability state.

But first, what makes a list mutable or immutable?

Immutable Collections

An immutable collection, as the name suggests, cannot be modified after it was created. This means:

  • Fixed Size: Once initialized, you cannot add, remove, or update elements in the collection.
  • Read-only: These collections provide read-only access to their elements. You can iterate over the elements, access them, but not add/replace or remove them.
  • Safety: Immutability guarantees that the collection won’t change unexpectedly. This is especially valuable in multi-threaded environments where concurrent modifications could lead to errors.
  • Kotlin Implementation: In Kotlin, immutable collections are created by default when you use functions like listOf(), setOf(), and mapOf().

Mutable Collections

Mutable collections, on the other hand, are dynamic. They allow:

  • Modification: You can add, remove, or update elements.
  • Variable Size: The size of the collection can change over time as elements are added or removed.
  • Kotlin Implementation: In Kotlin, mutable collections are explicitly created using functions like mutableListOf(), mutableSetOf(), and mutableMapOf().

On the safety side, mutable collections are prone to issues if used without being mindful. That is because their size can change at any time and from lots of places in your code and it makes debugging issues harder.

Having this said, let’s dive in and see the options we have in Kotlin.

Kotlin collections and mutability

List (immutable)

First of all let’s initialize a List in Kotlin:

val list: List<String> = listOf("Apple", "Cherry", "Carrot")

Important!

In Kotlin, lists are immutable by default (you can’t add or remove elements after the list is created). If you need to make a list mutable, you can do this by using MutableList and mutableListOf to quickly create a mutable list.

MutableList (mutable)

Bellow you can see mutableListOf in action and then adding a new item to the mutable list. The example uses a mutable list of String in this case but obviously it can be used any type of class.

val list: List<String> = mutableListOf<>("Apple", "Cherry", "Carrot")
list.add("Cucumber")

Additionally, to create a mutable list one can use an ArrayList like you see bellow.

val list: ArrayList<String> = arrayListOf("Apple", "Cherry", "Carrot") //mutable

Prefer imutable lists over mutable ones whenever possible because it adds clarity when comes to data source of truth and also makes the code more easy to debug(also less error prone due to the fact that your list won’t be able to be updatable from x places).

Mixed types

When you create a list in Kotlin, you can add mixed class types to the same list:

 val list = listOf("Apple", "Cherry", 100, true)

listOfNotNull() Function

val fruit = null
val list = listOfNotNull("Apple", "Cherry", fruit)

for (i in list) {
   println(i)
}

The output of the above code will be this:

Apple
Cherry

Notice that null values are ignored. See also the Kotlin Functions article.

Empty lists

There are a few ways to create empty lists. They do the same thing, so it’s up to you which way you prefer. Of course they both create immutable lists.

val list = listOf<String>()

OR

val list = emptyList<String>()

Set (immutable)

If you need to create an unordered list in Kotlin having unique elements, you can use a Set. Like Lists, the Set is also a collection that can be used either as mutable or immutable structure depending on the implementation and the usage. Also, I recommend the same rule as for the lists, prefer immutable over mutable ones whenever is possible to avoid potential malicious or unintended usage.

Create a Set in Kotlin

val set = setOf("Apple", "Cherry", "Carrot") //immutable

HashSet in Kotlin (mutable)

val set = hashSetOf("Apple", "Cherry", "Carrot") //mutable

Create a SortedSet (TreeSet in Java – mutable)

val set = sortedSetOf("Apple", "Cherry", "Carrot") //mutable

Initialize a LinkedSet (LinkedHashSet in Java – mutable)

val set = linkedSetOf("Apple", "Cherry", "Carrot") //mutable

Map (immutable)

In Kotlin, as in many other programming languages, a Map is a fundamental data structure that is useful for a variety of reasons. Here’s a few of them:

  • Key-Value Pair Storage: A Map stores data in key-value pairs, making it efficient to look up a value based on its key. This is particularly useful when you need to quickly retrieve data without searching through an entire list, as long as you have the key.
  • Efficient Lookup: Retrieval of values based on keys is typically very fast in a map, especially in implementations like HashMap where average time complexity for many operations (like get and put) is O(1).
  • Uniqueness of Keys: Each key in a map is unique. This characteristic makes maps ideal for cases where you need to prevent duplicate entries, like storing unique identifiers mapped to specific data.

Create a Map

val map = mapOf(1 to "John", 2 to "Chloe", 3 to "Maria") //immutable

How to iterate a Map?

val map = mapOf(1 to "John", 2 to "Chloe", 3 to "Maria")

for ((key, value) in map) {
     println("$value has the id = $key")
}

HashMap, LinkedMap (LinkedHashMap in Java) and SortedMap are all mutable.

Useful methods

any()

Returns true if collection has at least one element.

val list = listOf("Apple", "Cherry", "Carrot")
println("The list has at least one element = ${list.any()}") //returns TRUE

any(predicate: (T) -> Boolean

Returns true if at least one element matches the given predicate.

val list = listOf("Apple", "Cherry", "Carrot")
println("The list has at least one element of 15 letters = ${list.any{it.length == 15}}") //returns FALSE

asReversed()

Returns a reversed read-only view of the original List.

val list = listOf("Apple", "Cherry", "Carrot")
println(list.asReversed())

Output

I/System.out: [Carrot, Cherry, Apple]

Maybe you are interested also in this article about common questions in Kotlin.

Exit mobile version