编写性能scala不可变集合

时间:2013-06-13 12:56:53

标签: scala collections seq

快速提问。我目前正在设计一些数据库查询,以便将相当大但不是大量的数据集提取到内存中,比如大约10k-100k的记录。

到目前为止,我一直在测试将这些结果集加载到scala.collection.immutable.Seq中,并发现它似乎花费了相当长的时间来构建集合。然而,如果我更改为Vector或List,则写入内存只需几分之一秒。

我的问题是,为什么Seq在这种情况下如此缓慢?如果是这样,在什么情况下使用Seq比Vector更合适?

由于

1 个答案:

答案 0 :(得分:11)

如果您发布相关代码段以及您在序列上调用的操作会有所帮助 - immutable.Seq使用List表示(请参阅https://github.com/scala/scala/blob/v2.10.2/src/library/scala/collection/immutable/Seq.scala#L42)。我的猜测是你一直在:+上使用immutable.Seq,它通过复制它附加到列表的末尾(可能会给你二次整体性能),当你切换到直接使用immutable.List,您已使用::附加到开头(为您提供线性表现)。

由于Seq只是一个List,所以当你附加到序列的开头时应该使用它 - cons运算符::只创建一个节点,将它链接到列表的其余部分,这与不可变数据结构的速度一样快。否则,如果您添加到最后,并且您坚持不变性,则应使用Vector(或即将发布的Conc列表!)。

如果您想验证这些声明,请参阅此link,其中使用ScalaMeter比较两个操作的性能 - 当您添加到开头时,列表比矢量快8倍。

但是,最合适的数据结构应该是ArrayBufferVectorBuilder。这些是可动态调整大小的可变数据结构,如果使用+=构建它们,您将获得合理的性能。这假设您没有存储基元。