【问题标题】:Scala: Most efficent collection for simple iterationScala:简单迭代的最有效集合
【发布时间】:2012-05-11 00:36:15
【问题描述】:

我经常按需生成集合以节省实例数据大小。消费者在收集垃圾之前可能只迭代一次集合。消费者不关心集合的顺序,不需要对其进行排序,当然也不需要改变它,或者它的任何元素。 Scala 中最有效的类型安全集合是什么? - 一个数组?

后来的编辑:我突然想到在很多情况下我可以使用 Sets。尽可能使用 Set 好还是只在真正需要 set 功能时才使用?

【问题讨论】:

  • 你为什么不测量它?我希望,如果你不只是迭代它们,找到终点——也许是为了获得集合大小,但对每个对象做一些实际的工作,花在每个对象上的时间超过了按顺序迭代的时间数量级。
  • @userunknown 集合遍历的基准在此处进行基准测试:paradigmatic.streum.org/2012/02/… 和此处:codedependents.com/2012/04/30/…

标签: scala scala-collections


【解决方案1】:

是的,在所有集合数据结构中,数组具有最少的开销如果您提前知道它们的大小。

如果您不提前知道大小,我仍然会选择 ArrayBuffer*。用于在空间不足时扩展底层数组的算法尽可能高效。

不要不*使用(链接的)List或Stream,因为这些类涉及每个元素一个堆分配时间>。现代 JVM 垃圾收集器很好,但它们不是免费的。

*:但请参阅@user unknown 对问题的评论以获取一些微基准的链接。当前的ArrayBuffer 实现可能不是最理想的。

还请查看 .view。通常您不需要实际存储中间结果。相反,您可以使用.map、.filter 和其他人来构建集合的“描述”。操作(映射、过滤器等)只会在您迭代集合时执行,通常在O(1) 空间中。不利的一面是,每次查询这些视图时都会重新计算它们。 (尽管使用简单的过滤器和庞大的底层集合可能仍然更有效)

另外,对可变数据结构的视图要格外小心。视图不捕获底层数据结构的状态。当它改变时,视图也会改变。然而,关于不可变数据结构的视图表现得非常好。最后,视图显然包含对底层数据结构的引用,这意味着当您的程序保留视图时,它不会被垃圾回收。

(更新) 向量似乎在存储效率和灵活性之间取得了很好的平衡,尤其是对于大型序列。

【讨论】:

  • 您是否知道在使用视图时应注意的任何其他问题(性能或其他)?
【解决方案2】:

您需要存储元素吗?你不能按需计算它们吗?如果您可以按需计算值而不是存储它们,您可以创建一个 Traversable 或 Iterable 来完成这项工作,几乎没有任何内存消耗(Traversable 没有内存消耗,除了类本身)。

【讨论】:

  • 在特定情况下,我认为不会。所以 Traversable 或 Iterable 在集合实际上没有被实例化的情况下似乎是一个不错的选择。
猜你喜欢
  • 1970-01-01
  • 2010-10-04
  • 1970-01-01
  • 1970-01-01
  • 2011-02-17
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多