在Scala 2.9.1中,这很好用:
scala> (1 to Int.MaxValue).sum
res6: Int = -1073741824
然而这用完了堆空间:
scala> (1 to Int.MaxValue).toIterator.sum
java.lang.OutOfMemoryError: GC overhead limit exceeded
但令人抓狂的是,这有效:
scala> (1 to Int.MaxValue).iterator.sum
res8: Int = -1073741824
为什么其中任何一个都不同?
答案 0 :(得分:8)
toIterator
在TraversableLike
中定义为
def toIterator: Iterator[A] = toStream.iterator
所以它在后台创建一个Stream
,在迭代时将所有元素保存在内存中。
(编辑:我认为实际上流结构不是问题。但是,toStream
本身会调用toBuffer
,而iterator
会复制每一个值。)< / p>
另一方面,
IndexedSeqLike
在{{1}}中定义,它使用一种不会在内存中保留任何元素的专门结构。
答案 1 :(得分:2)
如果仔细查看代码,就会知道所有内容的定义。
当你调用toIterator时,它会接受序列中的所有内容并将其复制到ArrayBuffer中(首先尝试将其转换为流。)此副本很可能是导致内存不足的原因。
使用迭代器时,它会创建一个返回BufferedIterator的受保护类Elements的实例。这使用类本身来返回元素。
protected class Elements(...) ... {
...
def next: A = {
if (index >= end)
Iterator.empty.next
val x = self(index)
index += 1
x
}
}