2016-05-29 57 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 - 这不完全是“不够聪明”的情况,而是“做你所要求的”。编译器也无法做到这种组合(总的来说,无论如何,优化器会得到特殊情况),但在这种情况下,它不应该做任何不同的事情,因为大概你有一些很好的理由要求一个由数组支持的视图,而不是一个范围。 –