Arrays and lists (represented by List<T> and its subtype MutableList<T>) have many differences, here are the most significant ones:
-
Array<T>is a class with known implementation: it’s a sequential fixed-size memory region storing the items (and on JVM it is represented by Java array).List<T>andMutableList<T>are interfaces which have different implementations:ArrayList<T>,LinkedList<T>etc. Memory representation and operations logic of lists are defined in concrete implementation, e.g. indexing in aLinkedList<T>goes through the links and takes O(n) time whereasArrayList<T>stores its items in a dynamically allocated array.val list1: List<Int> = LinkedList<Int>() val list2: List<Int> = ArrayList<Int>() -
Array<T>is mutable (it can be changed through any reference to it), butList<T>doesn’t have modifying methods (it is either read-only view ofMutableList<T>or an immutable list implementation).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 -
Arrays have fixed size and cannot expand or shrink retaining identity (you need to copy an array to resize it). As to the lists,
MutableList<T>hasaddandremovefunctions, so that it can increase and reduce its size.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>is invariant onT(Array<Int>is notArray<Number>), the same forMutableList<T>, butList<T>is covariant (List<Int>isList<Number>).val a: Array<Number> = Array<Int>(0) { 0 } // won't compile val l: List<Number> = listOf(1, 2, 3) // OK -
Arrays are optimized for primitives: there are separate
IntArray,DoubleArray,CharArrayetc. which are mapped to Java primitive arrays (int[],double[],char[]), not boxed ones (Array<Int>is mapped to Java’sInteger[]). Lists in general do not have implementations optimized for primitives, though some libraries (outside JDK) provide primitive-optimized lists. -
List<T>andMutableList<T>are mapped types and have special behaviour in Java interoperability (Java’sList<T>is seen from Kotlin as eitherList<T>orMutableList<T>). Arrays are also mapped, but they have other rules of Java interoperability. -
Certain array types are used in annotations (primitive arrays,
Array<String>, and arrays withenum classentries), and there’s a special array literal syntax for annotations. Lists and other collections cannot be used in annotations. -
As to the usage, good practice is to prefer using lists over arrays everywhere except for performance critical parts of your code, the reasoning is the same to that for Java.
The major difference from usage side is that Arrays have a fixed size while (Mutable)List can adjust their size dynamically. Moreover Array is mutable whereas List is not.
Furthermore kotlin.collections.List is an interface implemented among others by java.util.ArrayList. It’s also extended by kotlin.collections.MutableList to be used when a collection that allows for item modification is needed.
On the jvm level, Array is represented by arrays. List on the other hand is represented by java.util.List since there are no immutable collections equivalents available in Java.