← Назад к вопросам

Как под капотом работает listOf

1.3 Junior🔥 91 комментариев
#Kotlin основы#Коллекции и структуры данных

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает listOf() под капотом

listOf() — это фабричная функция из стандартной библиотеки Kotlin (kotlin-stdlib), предназначенная для создания неизменяемых (immutable) списков. Её реализация глубоко оптимизирована для производительности и удобства.

1. Тип возвращаемого значения

Функция возвращает интерфейс List<T>, который в Kotlin по умолчанию является неизменяемым (не имеет методов добавления/удаления элементов). Конкретная реализация зависит от количества переданных аргументов:

val emptyList = listOf<String>()        // возвращает EmptyList
val singleList = listOf("A")           // возвращает SingletonList
val multiList = listOf("A", "B", "C")  // возвращает Arrays.asList() или подобную

2. Реализация для разных случаев

Пустой список (listOf() без аргументов)

Возвращает специальный синглтон-объект EmptyList, который: -Takes zero memory for storage -Is thread-safe -Optimized for all operations

// Упрощённая логика из исходного кода Kotlin
public fun <T> listOf(): List<T> = emptyList()

internal object EmptyList : List<Nothing>, Serializable {
    override val size: Int get() = 0
    override fun isEmpty(): Boolean = true
    override fun get(index: Int): Nothing = throw IndexOutOfBoundsException()
    // ... остальные методы
}

Список с одним элементом (listOf(element))

Используется SingletonList для минимального потребления памяти:

// Примерная реализация
internal class SingletonList<out E>(private val element: E) : List<E>, Serializable {
    override val size: Int = 1
    override fun get(index: Int): E {
        if (index != 0) throw IndexOutOfBoundsException()
        return element
    }
    // ... остальные методы
}

Список с несколькими элементами

Используется реализация на основе массива:

// Фактически вызывает Arrays.asList() или аналогичную оптимизированную реализацию
public fun <T> listOf(vararg elements: T): List<T> = 
    if (elements.size > 0) elements.asList() else emptyList()

// Внутри elements.asList() может создавать:
// 1. ArrayList (обёртка над массивом)
// 2. Прямую обёртку над переданным массивом без копирования

3. Ключевые особенности реализации

Оптимизация памяти:

  • Для 0 и 1 элемента — специализированные объекты
  • Для нескольких элементов — обёртка над исходным массивом
  • Минимальные накладные расходы

Неизменяемость:

  • Возвращаемый список не поддерживает методы изменения
  • Любая попытка модификации выбросит UnsupportedOperationException
  • Это достигается возвратом java.util.Collections.UnmodifiableList или аналогичной реализации

Взаимодействие с Java:

// Kotlin
val kotlinList = listOf("A", "B", "C")

// В Java это будет восприниматься как java.util.List
// Но попытка вызвать add() выбросит исключение

4. Важные детали

  • Передача массива: При использовании vararg элементы копируются в новый массив
  • Null-безопасность: listOfNotNull() игнорирует null-значения
  • Производительность: Создание списка — операция O(1) для пустого и одноэлементного, O(n) для множественного (из-за копирования массива)
  • Сериализуемость: Все реализации поддерживают сериализацию

5. Практический пример различий

fun analyzeLists() {
    val empty = listOf<String>()      // EmptyList (синглтон)
    val single = listOf("Kotlin")     // SingletonList
    val multi = listOf(1, 2, 3)       // Arrays.ArrayList или аналог
    
    println(empty::class.java.simpleName)   // "EmptyList"
    println(single::class.java.simpleName)  // "SingletonList"
    println(multi::class.java.simpleName)   // "ArraysArrayList" или подобное
}

6. Сравнение с mutableListOf()

Важно отличать от изменяемого аналога:

val immutable = listOf(1, 2, 3)        // Нельзя изменить
val mutable = mutableListOf(1, 2, 3)   // Можно изменять

// immutable.add(4)    // Ошибка компиляции/UnsupportedOperationException
mutable.add(4)         // Успешно

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