2011-11-23 47 views
4

在斯卡拉2.9.1,这工作得很好:为什么会Scala范围迭代器缓冲区 - 有时候?

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 

为什么要任何那些有所不同?

回答

7

toIteratorTraversableLike定义为

def toIterator: Iterator[A] = toStream.iterator 

因此它创建在其保持在存储器中的所有元素,同时重复所述背景Stream

编辑:我认为流结构是不是这里的问题其实然而,toStream本身调用toBuffer这反过来副本的每一个值。)

iterator,另一方面是IndexedSeqLike定义它使用一种专门的结构,不会在内存中保留任何元素。

+4

换句话说,这是一个错误;带有'iterator'方法的类(至少不可变的方法)应该重写'toIterator'来简单地调用'iterator'。 –

+1

是的,夜间修复。 – Debilski

+0

我正在使用2.10.3和(1到Int.MaxValue).iterator.sum为我消耗大量内存。我无法理解为什么.. –

2

如果仔细查看代码,就是如何定义所有内容。

当您调用toIterator时,它会将序列中的所有内容都复制到一个ArrayBuffer中(首先尝试将其转换为流)。此复制可能是导致内存不足的原因。

当您使用迭代器时,它创建一个受保护的类的实例,它返回一个BufferedIterator。这使用类本身来返回元素。

protected class Elements(...) ... { 
    ... 
    def next: A = { 
     if (index >= end) 
      Iterator.empty.next 

     val x = self(index) 
     index += 1 

     x 
    } 
} 
相关问题