Avatar ·

Как инициализировать пустой MutableList в Kotlin?

Привет! Я только начал изучать Kotlin после Java и столкнулся с проблемой при работе со списками. Мне нужно создать изменяемый список (MutableList), но я хочу, чтобы он изначально был пустым, чтобы потом добавлять в него элементы динамически. В Java я привык делать так: ```java List list = new ArrayList<>(); ``` Но в Kotlin я вижу несколько способов и не понимаю, какой из них правильный. Я пробовал: ```kotlin val myList = mutableListOf() ``` Но компилятор ругается: "Type inference failed. Expected type mismatch." Потом я попробовал: ```kotlin var myList: MutableList = mutableListOf() ``` Это вроде работает, но я не уверен, что это лучший способ. Ещё я видел в документации что-то про `ArrayList()` и `emptyList()`, но `emptyList()` возвращает неизменяемый список, а мне нужен изменяемый. Подскажите, пожалуйста, как правильно инициализировать пустой MutableList в Kotlin? Какой способ считается идиоматичным и почему? Есть ли разница между разными подходами по производительности или читаемости кода? Заранее спасибо за помощь! <<>>

Основной способ: mutableListOf()

Самый простой и идиоматичный способ создать пустой изменяемый список в Kotlin — использовать функцию mutableListOf() с явным указанием типа:

val myList: MutableList<String> = mutableListOf()

Если вы укажете тип переменной, Kotlin сможет вывести тип элементов списка автоматически. Этот способ предпочтителен, так как:

  • Чётко выражает намерение создать изменяемый список
  • Использует стандартную фабричную функцию из стандартной библиотеки
  • Работает с любыми типами данных

Почему mutableListOf() без типа не работает?

Когда вы пишете val myList = mutableListOf(), компилятор не может определить, какой тип элементов будет у списка. Kotlin строго типизирован, поэтому требуется явная аннотация или контекст, из которого тип можно вывести. Например, если сразу добавить элемент:

val myList = mutableListOf("first")  // Тип String выводится автоматически

Альтернативные подходы

Вот несколько других способов создать пустой MutableList:

1. Использовать ArrayList напрямую:

val myList = ArrayList<String>()

Это тоже корректно, так как ArrayList реализует интерфейс MutableList. Однако mutableListOf() считается более идиоматичным и даёт возможность в будущем изменить реализацию (например, на LinkedList), не меняя код.

2. Использовать конструктор MutableList с размером:

val myList = MutableList<String>(0) { "" }

Создаёт список с начальной ёмкостью 0. Редко используется, так как менее читаемо.

3. Создать пустой список и преобразовать его:

val myList = emptyList<String>().toMutableList()

Работает, но создаёт лишний объект (неизменяемый список), который сразу же преобразуется. Неэффективно.

Рекомендации по использованию

  • Для большинства случаев используйте val myList: MutableList<String> = mutableListOf()
  • Если нужна конкретная реализация (например, для производительности), используйте ArrayList() или LinkedList()
  • Избегайте создания списка через emptyList().toMutableList() — это лишняя работа для GC
  • Для неизменяемых списков используйте listOf() или emptyList()

Пример использования в коде

fun main() {
    val fruits: MutableList<String> = mutableListOf()
    fruits.add("Apple")
    fruits.add("Banana")
    fruits.add("Cherry")
    
    println(fruits)  // [Apple, Banana, Cherry]
    
    // Изменяем список
    fruits.remove("Banana")
    fruits[0] = "Apricot"
    
    println(fruits)  // [Apricot, Cherry]
}

В заключение: mutableListOf() с явным указанием типа — это правильный и идиоматичный способ создания пустого изменяемого списка в Kotlin. Он понятен, эффективен и соответствует стилю языка.

<<>>

Использование конструктора ArrayList с указанием ёмкости

Если вы точно знаете, что в будущем в списке будет много элементов, можно сразу задать начальную ёмкость (capacity) для оптимизации производительности:

val myList = ArrayList<String>(100)  // Ёмкость 100 элементов

Этот способ полезен, когда вы заранее знаете примерное количество элементов. Он позволяет избежать многократного перераспределения памяти при добавлении элементов. Однако помните, что ёмкость — это не размер списка, а зарезервированная память. Сам список остаётся пустым (size == 0), но при добавлении первых 100 элементов не будет происходить внутреннего копирования массива.

Когда это лучше mutableListOf()?

  • При работе с большими наборами данных (тысячи и более элементов)
  • В циклах, где критична производительность
  • Если вы точно знаете максимальный размер списка

Для обычных случаев (списки до 100-200 элементов) разница в производительности незаметна, и mutableListOf() остаётся предпочтительным вариантом из-за читаемости и лаконичности.