Reputation: 7744
What is the difference between List
and Array
types?
It seems can make same operations with them (loops, filter expression, etc..), is there any difference in behavior or usage?
val names1 = listOf("Joe","Ben","Thomas")
val names2 = arrayOf("Joe","Ben","Thomas")
for (name in names1)
println(name)
for (name in names2)
println(name)
Upvotes: 366
Views: 163027
Reputation: 1785
IMO major difference between an array and a list is mutability, an array supports modifying the elements but a list does not. also, both of them are a type of fixed size.
When to use what? If you know you will have to modify the elements during your processing then go with the array else list.
Resizing:
During your process, if you want to resize the number of the elements then go for either arrayListOf()
or mutableListOf()
, beware of using these as these work on growable data structures
.
Upvotes: 0
Reputation: 1384
Explanation with a complex object
// lets define a data class
data class Color(var name : String)
// lets define all 3 - array, list and mutableList for this Color object
val array = arrayOf(Color("Red"))
val list = listOf(Color("Red"))
val mutableList = mutableListOf(Color("Red"))
array.add(Color("Green")) // Not Possible - cannot change size
array[0] = Color("Green") // Possible - array object can be changed
array[0].name = "Green" // Possible - object modification allowed by its class
list.add(Color("Green")) // Not Possible - cannot change size
list[0] = Color("Green") // Not Possible - list object cannot be changed
list[0].name = "Green" // Possible - object modification allowed by its class
mutableList.add(Color("Green")) // Possible - can change size
mutableList[0] = Color("Green") // Possible - can change object
mutableList[0].name = "Green" // Possible - object modification allowed by its class
Conclusions :
NOTE : This doesn't specify anything about the mutability of the object themselves. i.e. if the data class has some property as mutable (var), its property can be modified.
Upvotes: 6
Reputation: 41608
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.
Upvotes: 73
Reputation: 3095
In additional to the above, identity comparison is also different:
val l1 = listOf("a")
val l2 = listOf("a")
var x = (l1 == l2) // => true
val a1 = arrayOf("a")
val a2 = arrayOf("a")
var y = (a1 == a2) // => false
Upvotes: 55
Reputation: 147911
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>
and MutableList<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 a LinkedList<T>
goes through the links and takes O(n) time whereas ArrayList<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), but List<T>
doesn't have modifying methods (it is either read-only view of MutableList<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>
has add
and remove
functions, 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 on T
(Array<Int>
is not Array<Number>
), the same for MutableList<T>
, but List<T>
is covariant (List<Int>
is List<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
, CharArray
etc. which are mapped to Java primitive arrays (int[]
, double[]
, char[]
), not boxed ones (Array<Int>
is mapped to Java's Integer[]
). Lists in general do not have implementations optimized for primitives, though some libraries (outside JDK) provide primitive-optimized lists.
List<T>
and MutableList<T>
are mapped types and have special behaviour in Java interoperability (Java's List<T>
is seen from Kotlin as either List<T>
or MutableList<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 with enum class
entries), 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.
Upvotes: 548