数组与列表在标量中的区别

在什么情况下我应该使用 Array (Buffer)和 List (Buffer)。我所知道的唯一区别是数组是非变量的,而列表是协变的。但是性能和其他一些特征呢?

80226 次浏览

不可变结构

Scala List是一个不可变的递归数据结构,它是 Scala 的一个基本结构,你应该(可能)比使用 Array更多地使用它(Array实际上是 易变的-Array永恒的模拟IndexedSeq)。

如果您来自 Java 背景,那么显而易见的相似之处是何时使用 LinkedList而不是 ArrayList。前者通常用于只有 穿越的列表(其大小在前面是未知的) ,而后者应该用于具有已知大小(或最大大小)或者对于 快速随机存取很重要的列表。

可变结构

ListBuffer提供了到 List的恒定时间转换,如果需要这样的后期转换,这就是单独使用 ListBuffer的原因。

Scala Array应该通过 Java 数组在 JVM 上实现,因此 Array[Int]可能比 List[Int]性能更好(作为一个 int[])(List[Int]会打包它的内容,除非你使用的是最新版本的 Scala,它具有新的 @specialized特性)。

然而,我认为在 Scala 中使用 Array应该保持在最低限度,因为感觉你真的需要知道底层发生了什么,以决定你的数组是否真的会被所需的原语类型支持,或者可能被装箱作为包装类型。

Array 是可变的,这意味着您可以更改每个索引的值,而 List (默认情况下)是不可变的,这意味着每次修改时都会创建一个新列表。在大多数情况下,处理不可变的数据类型是一种更“功能性”的风格,您可能应该尝试使用 List 和诸如 yieldforeachmatch等结构。

对于性能特征,Array 在随机访问元素时更快,而 List 在预置(添加)新元素时更快。对它们进行迭代是可以比较的。

除了已经公布的答案,这里还有一些细节。

虽然 Array[A]实际上是一个 Java 数组,但是 List[A]是一个不可变的数据结构,它要么是 Nil(空列表) ,要么是由一对 (A, List[A])组成。

性能差异

                          Array  List
Access the ith element    θ(1)   θ(i)
Delete the ith element    θ(n)   θ(i)
Insert an element at i    θ(n)   θ(i)
Reverse                   θ(n)   θ(n)
Concatenate (length m,n)  θ(n+m) θ(n)
Count the elements        θ(1)   θ(n)

记忆差异

                          Array  List
Get the first i elements  θ(i)   θ(i)
Drop the first i elements θ(n-i) θ(1)
Insert an element at i    θ(n)   θ(i)
Reverse                   θ(n)   θ(n)
Concatenate (length m,n)  θ(n+m) θ(n)

因此,除非您需要快速随机访问,需要计数元素,或者由于某种原因需要破坏性更新,否则 ListArray更好。