快速提问。我目前正在设计一些数据库查询,以便将相当大但不是大量的数据集提取到内存中,比如大约10k-100k的记录。
到目前为止,我一直在测试将这些结果集加载到scala.collection.immutable.Seq中,并发现它似乎花费了相当长的时间来构建集合。然而,如果我更改为Vector或List,则写入内存只需几分之一秒。
我的问题是,为什么Seq在这种情况下如此缓慢?如果是这样,在什么情况下使用Seq比Vector更合适?
由于
答案 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倍。
但是,最合适的数据结构应该是ArrayBuffer
或VectorBuilder
。这些是可动态调整大小的可变数据结构,如果使用+=
构建它们,您将获得合理的性能。这假设您没有存储基元。