Scala 流vs视图vs迭代器

Scala 流vs视图vs迭代器,scala,scala-collections,Scala,Scala Collections,scala中的流、视图(SeqView)和迭代器之间有什么区别?这是我的理解: 它们都是懒惰的列表 流缓存这些值 迭代器只能使用一次?您不能返回到开始并再次计算该值吗 视图的值不会被缓存,但您可以反复计算它们 因此,如果我想节省堆空间,我应该使用迭代器(如果我不再遍历列表)还是视图?谢谢 首先,它们都是不严格的。这对函数有特殊的数学意义,但基本上意味着它们是按需计算的,而不是预先计算的 Stream确实是一个惰性列表。事实上,在Scala中,流是一个列表,其尾部是一个惰性val。计算后,值保

scala中的流、视图(SeqView)和迭代器之间有什么区别?这是我的理解:

  • 它们都是懒惰的列表
  • 流缓存这些值
  • 迭代器只能使用一次?您不能返回到开始并再次计算该值吗
  • 视图的值不会被缓存,但您可以反复计算它们
因此,如果我想节省堆空间,我应该使用迭代器(如果我不再遍历列表)还是视图?谢谢

首先,它们都是不严格的。这对函数有特殊的数学意义,但基本上意味着它们是按需计算的,而不是预先计算的

Stream
确实是一个惰性列表。事实上,在Scala中,
是一个
列表
,其
尾部
是一个
惰性val
。计算后,值保持计算状态并被重用。或者,正如您所说,这些值是缓存的

迭代器只能使用一次,因为它是指向集合的遍历指针,而不是集合本身。Scala中的特殊之处在于,您可以应用变换,例如
map
filter
,只需获得一个新的
迭代器,它将仅在您请求下一个元素时应用这些变换

Scala曾经提供可以重置的迭代器,但这在一般情况下是很难支持的,并且他们没有将版本2.8.0

视图的查看方式与数据库视图非常相似。这是一系列转换,应用于集合以生成“虚拟”集合。正如您所说,每次需要从中获取元素时,都会重新应用所有转换

迭代器和视图都具有出色的内存特性
Stream
很好,但在Scala中,它的主要优点是编写无限序列(特别是递归定义的序列)。通过确保不保留对其
头的引用(例如,使用
def
而不是
val
来定义
流,可以避免将所有
保留在内存中


由于视图会受到惩罚,通常应在应用转换后
强制它,或者如果与视图的总大小相比,只需提取很少的元素,则应将其保留为视图。

迭代器
对于探测无限空间也非常方便,在可能的情况下,我通常更喜欢它们而不是溪流。流中真正的好处是缓存以前访问的值,这对于尝试实现类似斐波那契序列的东西是一个很大的好处,斐波那契序列是根据以前的值定义的。斐波那契是一个不太完美的例子,因为它只需要前两个值,而保留整个流是一种浪费。Ackermann函数可能是一个典型的例子。@JürgenStrobel Ackermann将导致糟糕的性能,因为流的索引访问是O(n)。但我同意fibonacci的说法。哦,对了。这使得流对于任何缓存方法来说都是一个糟糕的选择。这个答案非常清楚,它应该是文档的一部分。。。哦,事实上是这样!谢谢丹尼尔--------------