В чем разница immutable и mutable коллекций в Kotlin и Java
Что проверяют
Понимаете ли вы, что в Kotlin разделение на уровне типов, а неизменяемость при этом не гарантирована по-настоящему. Это тонкое место, и его любят спрашивать.
Как отвечать
В Kotlin два набора интерфейсов: List, Set, Map только для чтения и MutableList, MutableSet, MutableMap для изменения.
val readOnly: List<Int> = listOf(1, 2, 3) // add нет вовсе
val mutable: MutableList<Int> = mutableListOf(1)
mutable.add(2)Важная точность: List это только для чтения, а не неизменяемый. Под ним может лежать изменяемый список, и если на него есть другая ссылка, содержимое поменяется у вас за спиной:
val source = mutableListOf(1, 2)
val view: List<Int> = source
source.add(3)
println(view) // [1, 2, 3]Настоящую неизменяемость даёт копия (toList()) или неизменяемые коллекции из kotlinx.immutable.
В Java разделения на уровне типов нет: List один, а неизменяемость даётся обёрткой Collections.unmodifiableList или фабриками List.of начиная с девятой версии. Попытка изменить бросает исключение в рантайме, а не отсекается компилятором.
Отдельно стоит развести val и неизменяемость коллекции: val запрещает переприсваивание ссылки, но не мешает менять содержимое MutableList.
Где спотыкаются
Считают List в Kotlin неизменяемым и удивляются изменившемуся содержимому.
Путают val с immutable.
Не знают, что коллекции из List.of в Java не принимают null и бросают исключение при любой попытке изменения, включая sort.