流 vs 视图 vs 迭代器
Posted
技术标签:
【中文标题】流 vs 视图 vs 迭代器【英文标题】:Stream vs Views vs Iterators 【发布时间】:2011-03-01 18:56:30 【问题描述】:scala 中的 Streams、Views (SeqView) 和 Iterators 有什么区别?这是我的理解:
都是惰性列表。 流缓存值。 迭代器只能使用一次?不能回到开头重新评估价值吗? 视图的值不会被缓存,但您可以一次又一次地评估它们?所以如果我想节省堆空间,我应该使用迭代器(如果我不会再次遍历列表)还是视图?谢谢。
【问题讨论】:
***.com/questions/4798043/… -------------- ***.com/questions/3361478/… 【参考方案1】:首先,它们都是非严格的。这具有与函数相关的特殊数学含义,但基本上意味着它们是按需而不是提前计算的。
Stream
确实是一个惰性列表。事实上,在 Scala 中,Stream
是 List
,其 tail
是 lazy val
。一旦计算出来,一个值就会保持计算状态并被重用。或者,正如您所说,这些值被缓存。
Iterator
只能使用一次,因为它是一个遍历指针到一个集合,而不是一个集合本身。它在 Scala 中的特别之处在于,您可以应用诸如 map
和 filter
之类的转换,并且只需获得一个新的 Iterator
,它只会在您请求下一个元素时应用这些转换。
Scala 曾经提供可以重置的迭代器,但这很难以一般方式支持,而且他们没有制作 2.8.0 版。
视图的查看方式与数据库视图非常相似。这是一系列转换,适用于集合以产生“虚拟”集合。正如您所说,每次您需要从中获取元素时,都会重新应用所有转换。
Iterator
和视图都具有出色的记忆特性。 Stream
很好,但是在 Scala 中,它的主要好处是编写无限序列(特别是递归定义的序列)。但是,可以避免将所有 Stream
保留在内存中,方法是确保不保留对其 head
的引用(例如,使用 def
而不是 @987654336 @ 定义Stream
)。
由于视图带来的惩罚,通常应该在应用转换后force
它,或者如果与视图的总大小相比,预计只获取很少的元素,则将其保留为视图。
【讨论】:
Iterator
对于探测无限来说也很方便,我通常更喜欢它们而不是流。流的真正好处是缓存了以前访问的值,这在尝试实现像斐波那契序列这样的东西时是一个很大的好处——它是根据以前的值定义的。
斐波那契不是一个完美的例子,因为它只需要前两个值,保留整个流是一种浪费。阿克曼函数可能是典型的例子。
@JürgenStrobel Ackermann 会导致糟糕的性能,因为流的索引访问是 O(n)。但我同意斐波那契。
哦,对了。这使得 Stream 成为任何缓存方法的糟糕选择。
这个答案超级清楚,应该是文档的一部分……哦,原来是这样!谢谢丹尼尔docs.scala-lang.org/tutorials/FAQ/stream-view-iterator.html以上是关于流 vs 视图 vs 迭代器的主要内容,如果未能解决你的问题,请参考以下文章
Iterables vs. Iterators vs. Generators(可迭代对象,迭代器,生成器)
c++ map使用问题和迭代器问题 编译器:VS2010旗舰版
querySelectorAll vs NodeIterator vs TreeWalker - 最快的纯JS平面DOM迭代器[关闭]