Как работает оператор плюс для коллекций в Kotlin
Что проверяют
Понимаете ли вы, что + для коллекций не меняет исходную коллекцию, а создаёт новую, и чем это грозит в цикле. Следом почти всегда спрашивают, чем += на val с MutableList отличается от += на var с List.
Как отвечать
+ это вызов функции-оператора plus из стандартной библиотеки. Результат всегда новая коллекция, исходная не меняется, даже если она изменяемая. Тип результата зависит от левого операнда:
List + элементилиList + коллекция: новыйList, правая часть дописана в конец, дубли сохраняются;Set + ...: новыйSet, дубли отбрасываются, порядок вставки сохраняется (под капотомLinkedHashSet);Map + PairилиMap + Map: новыйMap, при совпадении ключа побеждает значение справа;Array + ...: новый массив через копирование;Sequence + ...: ленивое объединение, ничего не копируется до терминальной операции.
Главная тонкость в +=. Для val list = mutableListOf(...) он вызывает plusAssign и меняет список на месте. Для var list = listOf(...) превращается в list = list + x: новый список и переприсваивание ссылки. А для var list = mutableListOf(...) компилятор сообщает о неоднозначности, потому что подходят оба варианта.
На Android это прямо связано с Compose и StateFlow: _items.value = _items.value + item создаёт новый неизменяемый список, ссылка меняется, и UI получает обновление. Если мутировать список внутри состояния, ни StateFlow, ни Compose об изменении не узнают.
Цена: каждое + копирует обе части, это O(n + m). Одно сложение не проблема, а result = result + x в цикле по тысячам элементов даёт квадратичную сложность. Там нужны buildList { }, MutableList или flatMap.
Где спотыкаются
Считают, что mutableList + x добавит элемент в сам список. Результат молча выбрасывается, а список остаётся прежним.
Собирают большой список через + в цикле и не видят в этом проблемы.
Ждут, что Map + Map сольёт значения по совпадающим ключам. Значение справа просто заменяет левое.