2011-11-23 46 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 
    } 
} 
相關問題