2016-05-29 63 views
0

我理解scala中的視圖結構的方式是該視圖是一個懶惰的集合,並且在訪問它之前沒有充滿真正的集合成員。 隨着該描述,下面的代碼行不應該拋出一個錯誤:查看範圍導致scala內存不足的錯誤

val a = (0 to 123456789).view 

,並預期它沒有。我(最有可能錯誤地)假設下面的代碼行相當於上面的代碼不應該拋出內存不足的錯誤之一:

val a = Array.range(0,123456789).view 

,但它會產生一個「java.lang.OutOfMemoryError:Java堆空間「錯誤。任何想法爲什麼這兩行代碼的行爲不同?

回答

3

讓我們打破它......

val a1: Range.Inclusive = (0 to 123456789) 
val a2: AnyRef with SeqView[Int, IndexedSeq[Int]] = a1.view 

val b1: Array[Int] = Array.range(0,123456789) 
val b2: AnyRef with mutable.IndexedSeqView[Int, Array[Int]] = b1.view 

的IntelliJ推斷(按CTR-Q)其中,b1是一個數組。

讓我們來看看該文檔的 「Array.range」 ......

/** Returns an array containing a sequence of increasing integers in a range. 
    * 
    * @param start the start value of the array 
    * @param end the end value of the array, exclusive (in other words, this is the first value '''not''' returned) 
    * @return the array with values in range `start, start + 1, ..., end - 1` 
    * up to, but excluding, `end`. 
    */ 
    def range(start: Int, end: Int): Array[Int] = range(start, end, 1) 

錯誤是從那裏你打電話Array.range行來了...

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at scala.collection.mutable.ArrayBuilder$ofInt.mkArray(ArrayBuilder.scala:323) 
    at scala.collection.mutable.ArrayBuilder$ofInt.resize(ArrayBuilder.scala:329) 
    at scala.collection.mutable.ArrayBuilder$ofInt.sizeHint(ArrayBuilder.scala:334) 
    at scala.Array$.range(Array.scala:402) 
    at scala.Array$.range(Array.scala:390) 
    at pkg.Main$.main(Main.scala:57) 
    at pkg.Main.main(Main.scala) 

你剛纔分配的其中包含123456790個元素的數組,這就是爲什麼您得到「java.lang.OutOfMemoryError:Java堆空間」錯誤。

+0

因此,如果我理解正確,Scala編譯器是不夠智能結合這兩個步驟? – TNM

+3

@TNM - 這不完全是「不夠聰明」的情況,而是「做你所要求的」。編譯器也無法做到這種組合(總的來說,無論如何,優化器會得到特殊情況),但在這種情況下,它不應該做任何不同的事情,因爲大概你有一些很好的理由要求一個由數組支持的視圖,而不是一個範圍。 –

相關問題