如果这是重复的道歉 - 我做了一些搜索并且找不到我需要的东西。
我们的应用程序具有性能关键部分,可将Play 2.0 Enumerator
(可被视为Stream
)转换为List
(或类似)。我们将在fold
上使用Enumerator
方法,问题是最有效的方法。 (我会在代码中使用Stream
代替Enumerator
,但这个想法应该是相同的。)
val incoming: Stream[Int] = ???
val result: Seq[Int] = incoming.fold(Seq.empty)(_ + _)
val result2: Seq[Int] = incoming.fold(MutableList.empty(_ += _).toSeq
所以问题基本上是,如何反复追加不可变的Vector
比较重复追加性能关键代码中的可变MutableList
或ListBuffer
?我们已经抛出List
,因为我们需要O(1)
追加(不是前置)。但是,可变数据结构是否在性能或垃圾收集方面为我们提供了任何东西?
答案 0 :(得分:17)
最好使用ArrayBuffer
。在我的机器上,您每秒可获得以下数量的附加内容:
preallocated Array[Int] -- 830M
resized (x2) Array[Int] -- 263M
Vector.newBuilder + result -- 185M
mutable.ArrayBuffer -- 125M
mutable.ListBuffer -- 100M
mutable.MutableList -- 71M
immutable.List + reverse -- 68M
immutable.Vector -- 8M
我认为你并不总是只是存储整数,并且你希望所有的集合都没有额外的包装,所以ArrayBuffer
是性能最佳的解决方案,只要你只需要追加到一端即可。该列表支持双向添加,具有可比性。相比之下,矢量非常慢 - 只有在你可以利用大量数据共享的情况下才使用它,或者一次性创建它们(参见Vector.newBuilder
结果,这太棒了;它是一个很棒的访问数据结构,迭代,创建和备用更新,而不是一直更新。