Ответ 1
Массивы и списки (представленные List<T>
и его подтипом MutableList<T>
) имеют много различий, вот наиболее значимые из них:
-
Array<T>
- это класс с известной реализацией: это последовательная область памяти фиксированного размера, в которой хранятся элементы (а в JVM она представлена массивом Java).List<T>
иMutableList<T>
являются интерфейсами, которые имеют разные реализации:ArrayList<T>
,LinkedList<T>
и т.д. Представление в памяти и логика операций списков определяются в конкретной реализации, например, выполняется индексация вLinkedList<T>
ссылки и занимают O (n) времени, тогда какArrayList<T>
хранит свои элементы в динамически размещаемом массиве.val list1: List<Int> = LinkedList<Int>() val list2: List<Int> = ArrayList<Int>()
-
Array<T>
является изменяемым (его можно изменить с помощью любой ссылки на него), ноList<T>
не имеет модифицирующих методов (это либо представлениеMutableList<T>
только дляMutableList<T>
либо реализация неизменяемого списка).val a = arrayOf(1, 2, 3) a[0] = a[1] // OK val l = listOf(1, 2, 3) l[0] = l[1] // doesn't compile val m = mutableListOf(1, 2, 3) m[0] = m[1] // OK
-
Массивы имеют фиксированный размер и не могут расширять или уменьшать сохраняющуюся идентичность (вам нужно скопировать массив, чтобы изменить его размер). Что касается списков,
MutableList<T>
имеет функцииadd
иremove
, так что он может увеличивать и уменьшать свой размер.val a = arrayOf(1, 2, 3) println(a.size) // will always be 3 for this array val l = mutableListOf(1, 2, 3) l.add(4) println(l.size) // 4
-
Array<T>
является инвариантом дляT
(Array<Int>
не являетсяArray<Number>
), то же самое дляMutableList<T>
, ноList<T>
является ковариантным (List<Int>
являетсяList<Number>
).val a: Array<Number> = Array<Int>(0) { 0 } // won't compile val l: List<Number> = listOf(1, 2, 3) // OK
-
Массивы оптимизированы для примитивов: есть отдельные
IntArray
,DoubleArray
,CharArray
и т.DoubleArray
,CharArray
сопоставляются с массивами примитивов Java (int[]
,double[]
,char[]
), а не в штучной упаковке (Array<Int>
сопоставляется с JavaInteger[]
). Как правило, списки не имеют реализаций, оптимизированных для примитивов, хотя некоторые библиотеки (за пределами JDK) предоставляют списки, оптимизированные для примитивов. -
List<T>
иMutableList<T>
являются отображенными типами и имеют особое поведение в совместимости с Java (JavaList<T>
рассматривается Kotlin какList<T>
илиMutableList<T>
). Массивы также отображаются, но у них есть другие правила взаимодействия Java. -
Определенные типы массивов используются в аннотациях (примитивные массивы,
Array<String>
и массивы с записямиenum class
), и существует специальный синтаксис литерала массива для аннотаций. Списки и другие коллекции не могут быть использованы в аннотациях. -
Что касается использования, хорошей практикой является предпочтение использования списков над массивами везде, за исключением критических с точки зрения производительности частей вашего кода, аргументация та же, что и для Java.