5

抱歉,如果这是重复的 - 我做了一些搜索,并没有找到我需要的东西。

我们的应用程序有一个性能关键部分,它将传入数据的 Play 2.0 Enumerator(可以被认为是 a )转换为 a (或类似的)。我们将使用该方法,问题是什么是最高效的方法。(我将在代码中使用而不是,但想法应该是相同的。)StreamListfoldEnumeratorStreamEnumerator

val incoming: Stream[Int] = ???
val result: Seq[Int] = incoming.fold(Seq.empty)(_ + _)
val result2: Seq[Int] = incoming.fold(MutableList.empty(_ += _).toSeq

所以问题本质上是,重复附加到不可变代码Vector与重复附加到可变代码MutableListListBuffer性能关键代码相比如何?List我们只是因为我们需要O(1)追加(而不是前置)而被抛出。但是可变数据结构在性能或垃圾收集方面能给我们带来什么好处吗?

4

1 回答 1

19

你可能最好使用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 慢得可怕——只有在您可以利用大量数据共享的情况下使用它,或者一口气创建它(见Vector.newBuilder结果,这太棒了;它是用于访问、迭代和创建的出色数据结构和备用更新,而不是一直更新)。

于 2012-12-27T18:09:14.357 回答