MutableList
中Scala的ListBuffer
和scala.collection.mutable
类有什么区别?你什么时候使用一个与另一个?
我的用例是一个线性序列,我可以有效地删除第一个元素,prepend和append。什么是最好的结构?
答案 0 :(得分:34)
关于它们如何运作的一点解释。
ListBuffer
使用内部Nil
和::
来构建不可变List
,并允许永久删除第一个和最后元素。为此,它将指针放在列表的第一个和最后一个元素上,并且实际上允许更改(否则是不可变的)::
类的头部和尾部({{1}允许的好技巧)成员private[scala] var
)。它的::
方法在常量时间内返回正常的不可变toList
,因为它可以直接返回内部维护的结构。它也是不可变List
的默认构建器(因此确实可以合理地期望具有恒定时间附加)。如果调用List
然后再将一个元素附加到缓冲区,则相对于缓冲区中当前元素数的线性时间将重新创建一个新结构,因为它不能再改变导出的列表。
toList
在内部与MutableList
合作,一个(公开的,不像LinkedList
)可变链接列表实现,它知道它的元素和后继(如::
)。 ::
还会保留指向第一个和最后一个元素的指针,但MutableList
会以线性时间返回,因为生成的toList
是从List
构建的。因此,在导出LinkedList
后,不需要重新初始化缓冲区。
根据您的要求,我会说List
和ListBuffer
是等价的。如果你想在某个时候导出他们的内部列表,那么问问自己你想要的开销:当你导出列表时,如果你继续改变缓冲区(然后去MutableList
),或者只有如果你再次改变缓冲区,并且在导出时没有(然后转到MutableList
)。
我的猜测是,在2.8集合大修中,ListBuffer
早于MutableList
和整个ListBuffer
系统。实际上,Builder
在MutableList
包中主要有用:它具有collection.mutable
方法,该方法以恒定时间返回,因此可以有效地用作维护所有结构的委托构建器内部private[mutable] def toLinkedList
。
所以我也建议使用LinkedList
,因为它可能会在未来获得关注和优化,而不是ListBuffer
和MutableList
等“纯粹可变”的结构。
答案 1 :(得分:7)
这为您提供了性能特征的概述:http://www.scala-lang.org/docu/files/collections-api/collections.html;有趣的是,MutableList
和ListBuffer
并没有区别。 MutableList
的文档说它在内部用作Stack
和Queue
的基类,所以从用户的角度来看,ListBuffer
可能更像是官方类吗?
答案 2 :(得分:5)
您想要一个可扩展和可收缩的列表(为什么是列表?),并且您需要不断的追加和前置。好吧,Buffer
,一个特征,具有不断的追加和前置,其他大多数操作是线性的。我猜测ListBuffer
,一个实现Buffer
的类,可以不间断地删除第一个元素。
所以,我自己的建议是ListBuffer
。
答案 3 :(得分:2)
首先,让我们来看看Scala中的一些相关类型
List
- 一个不可变的集合。递归实现,即。即列表实例有两个主要元素:头部和尾部,尾部引用另一个List
。
List[T]
head: T
tail: List[T] //recursive
LinkedList
- 一个可变集合,定义为一系列链接节点,其中每个节点都包含一个值和指向下一个节点的指针。
Node[T]
value: T
next: Node[T] //sequential
LinkedList[T]
first: Node[T]
List是一个功能数据结构(immutability),与LinkedList相比,在命令式语言中更为标准。
现在,让我们来看看
ListBuffer
- 由 List
支持的可变缓冲区实施。
MutableList
- 基于LinkedList的实现(如果已将其命名为 LinkedListBuffer
,则会更加自我解释)
They both offer similar complexity bounds on most operations.
但是,如果您从List
请求MutableList
,则必须将现有的线性表示转换为递归表示,该表示采用O(n),这是@ Jean-Philippe Pellet指出的出。但是,如果您从Seq
请求MutableList
,则复杂度为O(1)。
因此,IMO的选择范围缩小到您的代码和您的偏好的细节。但是,我怀疑还有更多List
和ListBuffer
。
答案 4 :(得分:0)
请注意,ListBuffer是final / sealed,而您可以扩展MutableList。 根据您的应用程序,可扩展性可能很有用。