Scala 可变列表和ListBuffer之间的区别

Scala 可变列表和ListBuffer之间的区别,scala,scala-collections,Scala,Scala Collections,Scala的Scala.collection.mutable中的MutableList和ListBuffer类之间有什么区别?你什么时候会用一个和另一个 我的用例有一个线性序列,在这个序列中,我可以有效地删除第一个元素prepend和append。这方面的最佳结构是什么?这为您提供了性能特征的概述:;有趣的是,MutableList和ListBuffer在这两个方面没有区别。MutableList的文档说明它在内部用作堆栈和队列的基类,因此从用户角度来看,ListBuffer可能更像是一个正式的

Scala的
Scala.collection.mutable
中的
MutableList
ListBuffer
类之间有什么区别?你什么时候会用一个和另一个


我的用例有一个线性序列,在这个序列中,我可以有效地删除第一个元素prepend和append。这方面的最佳结构是什么?

这为您提供了性能特征的概述:;有趣的是,
MutableList
ListBuffer
在这两个方面没有区别。
MutableList
的文档说明它在内部用作
堆栈和
队列的基类,因此从用户角度来看,
ListBuffer
可能更像是一个正式的类?

您想要一个可扩展和可收缩的列表(为什么是列表?),并且需要常量追加和前置。嗯,
Buffer
,一种特性,具有常量append和prepend,而大多数其他操作是线性的。我猜
ListBuffer
,一个实现
Buffer
的类,有固定时间删除第一个元素


因此,我个人的建议是对它们的工作原理做一点解释

ListBuffer
在内部使用
Nil
构建一个不可变的
列表
,并允许固定时间删除第一个和最后一个元素。为此,它将指针保留在列表的第一个和最后一个元素上,并且实际上允许更改(否则是不可变的)
类的头和尾(由
私有[scala]var
成员允许的好把戏)。它的
toList
方法也会在固定时间内返回正常的不可变
List
,因为它可以直接返回内部维护的结构。它也是不可变的
列表
s的默认构建器(因此可以合理地预期它具有恒定的时间附加)。如果调用
toList
,然后再次将一个元素附加到缓冲区中,则需要与缓冲区中当前元素数成线性关系的时间来重新创建新结构,因为它不能再改变导出的列表

MutableList
在内部与
LinkedList
一起工作,而是一个(公开的,不象
)可变链表实现,它知道其元素和后续元素(象
MutableList
还保留指向第一个和最后一个元素的指针,但是
toList
以线性时间返回,因为生成的
List
是从
LinkedList
构建的。因此,在导出
列表后,无需重新初始化缓冲区

考虑到您的需求,我认为
ListBuffer
MutableList
是等效的。如果你想在某个时候导出他们的内部列表,那么问问你自己在哪里需要开销:当你导出列表时,如果你继续修改缓冲区(然后选择
MutableList
),那么就没有开销,或者只有当你再次修改缓冲区,并且在导出时没有开销(然后选择
ListBuffer

我的猜测是,在2.8集合大修中,
MutableList
早于
ListBuffer
和整个
Builder
系统。实际上,
MutableList
集合中非常有用。mutable
包:它有一个
private[mutable]def-toLinkedList
方法,该方法以恒定时间返回,因此可以有效地用作内部维护
LinkedList
的所有结构的委托生成器


因此,我还建议您使用
ListBuffer
,因为它将来可能会比
MutableList
LinkedList
等“纯可变”结构更受关注和优化。首先,让我们看一下Scala中的一些相关类型

列表
-不可变的集合。递归实现,即。i、 一个list实例有两个主要元素head和tail,其中tail引用另一个
list

List[T]
  head: T
  tail: List[T]  //recursive
LinkedList
-定义为一系列链接节点的可变集合,其中每个节点包含一个值和指向下一个节点的指针

Node[T]
  value: T
  next: Node[T]  //sequential

LinkedList[T]
  first: Node[T]
与在命令式语言中更为标准的LinkedList相比,List是一种功能性数据结构(不变性)

现在,让我们看看

ListBuffer
-一种由
列表支持的可变缓冲区实现

MutableList
-一个基于LinkedList的实现(如果它被命名为
LinkedListBuffer
,则更容易解释)

但是,如果您从
可变列表
请求
列表
,那么它必须将现有的线性表示转换为递归表示,该表示采用O(n),这是@Jean-Philippe Pellet指出的。但是,如果您从
MutableList
请求
Seq
,复杂性为O(1)


因此,在我看来,选择范围缩小到您的代码和偏好的细节。不过,我怀疑还有更多的
List
ListBuffer

请注意,ListBuffer是最终的/密封的,而您可以扩展可变列表。
根据您的应用程序,可扩展性可能很有用。

我认为ListBuffer不允许常数时间获取/删除最后一个元素!看来你是对的——似乎不是。太糟糕了,因为它很容易做到。