Kotlin中List类型和Array类型的区别

349
< p >什么是ListArray类型之间的区别?
它们似乎可以执行相同的操作(循环、筛选表达式等),但在行为或使用上有什么区别吗?< /p >
val names1 = listOf("Joe","Ben","Thomas")
val names2 = arrayOf("Joe","Ben","Thomas")

for (name in names1)
    println(name)
for (name in names2)
    println(name)
4个回答

527

数组和列表(由List<T>及其子类型MutableList<T>表示)有许多不同之处,以下是其中最重要的几点:

  • 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.


71
使用方面的主要区别在于 数组 具有固定大小,而 (Mutable)List 可以动态调整其大小。此外,Array 是可变的,而 List 不可变。
此外,kotlin.collections.List 是一个接口,被实现在其他类中,包括 java.util.ArrayList。它也被 kotlin.collections.MutableList 扩展,用于需要允许项目修改的集合。
在 jvm 级别上,Array数组 表示。另一方面,List 则由 java.util.List 表示,因为 Java 中没有等效的不可变集合。

我在这里并不完全信服。Array 中可变的是什么?只有它的元素 - List 中也是一样的。List 的大小也是固定的。 - AndroidEx
7
@AndroidEx,以下代码可以编译通过:val intArray = arrayOf(1,2,3); intArray[0] = 2,然而以下代码编译不会通过:val intList = listOf(1,2,3); intList[0] = 2。虽然List具有固定的大小,但是继承它的MutableList并没有,因此一个val a:List<Int>在后续调用时可能会报告不同的size - miensol
1
使用List还是ArrayList更好? - IgorGanapolsky
4
如果你不关心具体的实现,可以使用 List(大概99%的情况下都可以用)。如果你关心实现细节,可以使用 ArrayListLinkedList 或其他具体的实现。 - miensol

53

除了上述内容外,身份比较也是不同的:

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

4
这个回答帮助我理解为什么使用数组的数据类建议你实现 equalshashCode 函数,而使用列表时则不需要。 - Kylaaa
1
在arrayOf()中出现false操作的原因是什么? - UNREAL

2

解释一个复杂的对象

// 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
  1. Methods on list
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

3. mutableList的方法
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

结论

  1. 数组和列表具有固定大小,因此无法添加或删除元素
  2. 列表无法修改,这意味着无法更改它所持有的对象
  3. 数组可以修改,这意味着可以更改它所持有的对象
  4. 可变列表可以执行任何操作,包括改变大小或其对象

注意:这并未指定对象本身的可变性。即如果数据类具有某个属性为可变(var),则可以修改该属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接