IntArray vs Array<Int> в Kotlin: в чем разница и что выбрать?
Основное различие: примитивы vs объекты
В Kotlin IntArray — это массив примитивных типов int (как в Java), а Array<Int> — массив ссылочных объектов Integer. Это ключевое отличие, которое влияет на память, производительность и поведение.
1. Производительность и память
- IntArray хранит значения непосредственно в памяти (как int[] в Java). Занимает 4 байта на элемент, без упаковки (boxing) и распаковки (unboxing).
- Array<Int> хранит ссылки на объекты Integer. Каждый элемент — это объект на куче (heap), что занимает 16-24 байта + накладные расходы на упаковку примитива.
Пример сравнения:
val millionInts = IntArray(1_000_000) // ~4 MB
val millionIntegers = Array(1_000_000) { 0 } // ~16-24 MB + overhead
Для больших массивов IntArray выигрывает в 4-6 раз по памяти и в 2-3 раза по скорости доступа.
2. Nullable и дженерики
IntArrayне может содержатьnull— это массив ненулевых примитивов.Array<Int?>может содержатьnull, так как это массив ссылок.Array<Int>(без ?) также не может содержатьnull, но при присваивании происходит упаковка.
Пример:
val ints = IntArray(3) // [0, 0, 0]
// ints[0] = null // Ошибка компиляции!
val objects = arrayOfNulls<Int>(3) // [null, null, null]
objects[0] = 42 // Упаковка int в Integer
3. Доступные методы
IntArray — это специализированный класс, который наследуется от Collection? Нет, он наследуется от Any, но имеет встроенные методы для работы с числами:
val arr = intArrayOf(1, 2, 3, 4, 5)
println(arr.sum()) // 15
println(arr.average()) // 3.0
println(arr.min()) // 1
println(arr.max()) // 5
Array<Int> таких методов не имеет — нужно использовать экстеншены:
val arr = arrayOf(1, 2, 3, 4, 5)
println(arr.sum()) // Работает через экстеншен, но медленнее из-за упаковки
4. Взаимодействие с Java
IntArrayкомпилируется вint[]— идеально для Java-библиотек.Array<Int>компилируется вInteger[]— может потребоваться преобразование.
Когда что выбирать?
- IntArray: для больших массивов чисел, где важна производительность и память (научные расчеты, графика, обработка сигналов).
- Array<Int>: когда нужны nullable элементы, работа с дженериками (например,
List<Array<Int>>) или совместимость с Java-кодом, ожидающимInteger[].
Как сделать универсальную функцию?
Если нужно работать и с IntArray, и с Array<Int>, используйте List<Int> или дженерики:
fun processNumbers(numbers: Collection<Int>) {
println("Сумма: ${numbers.sum()}")
}
// Работает с обоими:
processNumbers(intArrayOf(1,2,3).toList())
processNumbers(arrayOf(1,2,3).toList())
Или сделайте перегрузку функций для обоих типов.
<<Дополнение: преобразование между типами
Если вы уже используете один тип, но нужно передать данные в функцию, ожидающую другой, используйте встроенные методы:
// IntArray -> Array<Int>
val intArray = intArrayOf(1, 2, 3)
val arrayFromInts: Array<Int> = intArray.toTypedArray()
// Array<Int> -> IntArray
val array = arrayOf(1, 2, 3)
val intArrayFromArray: IntArray = array.toIntArray()
Особенности копирования
При преобразовании создается новый массив — копирование данных. Для больших массивов это может быть дорого. Старайтесь сразу выбирать правильный тип.
Когда IntArray может быть неудобен?
- Если вы используете функции высшего порядка (например,
map,filter), результат часто возвращается какList, а неIntArray. - Для работы с API, ожидающими
List<Int>, проще использоватьArray<Int>илиList<Int>.
Совет для новичков
Начинайте с List<Int> — это универсальный тип, который часто используется в Kotlin. Переходите на IntArray только когда профилирование покажет проблемы с производительностью. В 90% случаев List или Array достаточно.
Ответов пока нет.
Войдите чтобы оставить ответ