[collections] Kotlin's List missing "add", "remove", Map missing "put", etc?

Confining Mutability to Builders

The top answers here correctly speak to the difference in Kotlin between read-only List (NOTE: it's read-only, not "immutable"), and MutableList.

In general, one should strive to use read-only lists, however, mutability is still often useful at construction time, especially when dealing with third-party libraries with non-functional interfaces. For cases in which alternate construction techniques are not available, such as using listOf directly, or applying a functional construct like fold or reduce, a simple "builder function" construct like the following nicely produces a read-only list from a temporary mutable one:

val readonlyList = mutableListOf<...>().apply {
  // manipulate your list here using whatever logic you need
  // the `apply` function sets `this` to the `MutableList`
  add(foo1)
  addAll(foos)
  // etc.
}.toList()

and this can be nicely encapsulated into a re-usable inline utility function:

inline fun <T> buildList(block: MutableList<T>.() -> Unit) = 
  mutableListOf<T>().apply(block).toList()

which can be called like this:

val readonlyList = buildList<String> {
  add("foo")
  add("bar")
}

Now, all of the mutability is isolated to one block scope used for construction of the read-only list, and the rest of your code uses the read-only list that is output from the builder.

UPDATE: As of Kotlin 1.3.70, the exact buildList function above is available in the standard library as an experimental function, along with its analogues buildSet and buildMap. See https://blog.jetbrains.com/kotlin/2020/03/kotlin-1-3-70-released/.