Stream#filter为1,000,000个项目运行内存不足

时间:2013-12-03 19:42:53

标签: scala out-of-memory

假设我的Stream长度1,000,000全部为1。

scala> val million = Stream.fill(100000000)(1)
million: scala.collection.immutable.Stream[Int] = Stream(1, ?)

scala> million filter (x => x % 2 == 0)
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

我得到Out of Memory例外。

然后,我尝试使用filter进行相同的List调用。

scala> val y = List.fill(1000000)(1)
y: List[Int] = List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ...

scala> y.filter(x => x % 2 == 0)
res2: List[Int] = List()

然而它成功了。

为什么Stream#filter内存不足,但List#filter完成得不错?

最后,对于大型流,filter会导致整个流的非惰性评估吗?

1 个答案:

答案 0 :(得分:3)

List的开销 - 单个对象(::的实例),每个元素有2个字段(2个指针)。

Stream的开销 - Cons的实例(有3个指针)加上Functiontl: => Stream[A])的实例,用于对每个元素Stream#tail进行延迟评估

所以你会在Stream上花费大约2倍的内存。

您已将Stream定义为val。或者,您可以将million定义为def - 在这种情况下,filter GC将删除所有创建的元素,然后您将获得回忆。

请注意,只有tail中的Stream是惰性的,head是严格的,所以filter严格评估,直到它获得满足给定谓词的第一个元素,并且从那里开始您的Stream filter迭代所有million流中没有此类元素,并将所有元素放入内存中。