article banner

Effective Kotlin Item 59: Consider using mutable collections

This is a chapter from the book Effective Kotlin. You can find it on LeanPub or Amazon.

The biggest advantage of using mutable collections instead of immutable collections is that their performance is faster. When we add an element to an immutable collection, we need to create a new collection and add all elements to it. Here is how this is currently implemented in Kotlin stdlib (Kotlin 1.2):

operator fun <T> Iterable<T>.plus(element: T): List<T> { if (this is Collection) return val result = ArrayList<T>() result.addAll(this) result.add(element) return result }

When we deal with bigger collections, adding multiple elements to another collection can be a costly process. This is why using mutable collections, especially if we often need to add elements, is a performance optimization. On the other hand, Item 1: Limit mutability taught us the advantages of using immutable collections for safety. Notice that these arguments rarely apply to local variables, where synchronization or encapsulation is rarely needed. This is why it generally makes more sense to use mutable collections for local processing. This is reflected in the standard library, where all collection processing functions are internally implemented using mutable collections:

inline fun <T, R> Iterable<T>.map( transform: (T) -> R ): List<R> { val size = if (this is Collection<*>) this.size else 10 val destination = ArrayList<R>(size) for (item in this) destination.add(transform(item)) return destination }

Instead of using immutable collections:

// This is not how map is implemented inline fun <T, R> Iterable<T>.map( transform: (T) -> R ): List<R> { var destination = listOf<R>() for (item in this) destination += transform(item) return destination }


Adding mutable collections to elements is generally faster, but immutable collections give us more control over how they are changed. However, in the local scope we generally do not need this control, so mutable collections should be preferred, especially in util functions, where element insertion might happen many times.