Коллекции, равенство и копирование
Почему val, List и copy не замораживают данные
Ссылка, интерфейс и значение
val запрещает переприсвоение переменной. List<T> предоставляет интерфейс чтения, но за ним может стоять изменяемый объект. Для снимка структуры списка используйте toList(); вложенные объекты при этом остаются общими. Kotlin: коллекции.
val mutable = mutableListOf("draft")
val view: List<String> = mutable
val snapshot = mutable.toList()
mutable += "ready"
println(view.size) // 2
println(snapshot.size) // 1
Копия модели
Сгенерированный data class.copy() копирует ссылки на поля, а equals учитывает свойства первичного конструктора. Поле, объявленное в теле класса, не становится частью такого равенства. Неизменяемость приходится обеспечивать устройством всей модели. Kotlin: data classes.
data class Cart(val items: MutableList<String>)
val first = Cart(mutableListOf("book"))
val second = first.copy()
second.items += "pen"
println(first.items.size) // 2
Цена ленивости
Sequence выполняет промежуточные операции при терминальном вызове и может остановиться на take. Это экономит ненужную работу, но добавляет накладные расходы. Короткая цепочка маленького списка не обязана ускориться. Эффекты внутри map делают различия порядка вычислений заметными. Kotlin: Sequence.
Для ключа hash-коллекции выбирайте данные с неизменным равенством и хэшем на время хранения. Для массивов сравнивайте содержимое через contentEquals, если нужна семантика значения. Kotlin: equality.
Основа отбора: draft/kotlin_base.md, draft/M++.md, draft/faq500.md.