创建3位数字产品流时出现内存不足异常 [英] OutOfMemory Exception when Creating Stream of 3 Digit Products
问题描述
我编写了一个函数,该函数生成由x位数字的乘积组成的Stream [Long].
I wrote a function that produces a Stream[Long] consisting of the products of x-digit numbers.
例如,2位数字是1到99(包括1和99).
For example, 2 digit numbers is 1 to 99 (inclusive).
def getXDigitProducts(x: Int): Stream[Long] = {
val MAX = Math.pow(10, x)
@tailrec
def go(outer: Int, inner: Int, acc: Stream[Long]): Stream[Long] =
(outer, inner) match {
case (MAX, _) => acc
case (_, MAX) => go(outer + 1, 1, acc)
case (_, _) => go(outer, inner + 1, Stream[Long](outer * inner) ++ acc)
}
go(1, 1, Stream[Long]())
}
Waltkthrough:
Waltkthrough:
> Example: getXDigitProducts(2) will produce a stream of:
>
> 1*1 1*2 1*3 ... 1*98 1*99
> 2*1 2*2 2*3 ... 2*98 2*99
> 99*1 99*2 99*3 ... 99*98 99*99
使用x = 2可行,但是传入x = 3会在outer = 668
上引发OutOfMemory
异常.
Using x = 2 works, but passing in x = 3 throws an OutOfMemory
exception on outer = 668
.
此异常的原因是什么?
What is the cause of this exception?
执行Stream[Long](outer * inner) ++ acc
时,是否存在一些中间流没有正确收集垃圾?
When executing Stream[Long](outer * inner) ++ acc
, is there some intermediate Stream that isn't getting properly garbage collected?
推荐答案
Floris绝对正确.一旦调用go
,它将仅在到达case (MAX, _)
后返回.此时,所有内容已创建并分配到内存中.
Floris is absolutely right. Once you call go
, it will only return once it reaches case (MAX, _)
. At that point, everything has been created and allocated in memory.
我看到您试图确保尾部递归,但是Stream
的窍门是不具有尾部递归.您要构建Stream
的 start ,并将递归调用附加到它.
I see you tried to ensure tail recursion, but the trick with Stream
is to not have tail recursion. You want to build the start of a Stream
, and append the recursion call to it.
这不会引起堆栈溢出问题,因为该函数将在该点返回,而不是递归,并且仅当您访问流中的该元素时才进行递归"调用-在更高级别堆栈.
This won't cause stack overflow problems because, instead of recursing, the function will return at that point, and the "recursive" call will only be made once you access that element of the stream -- at a higher level in the stack.
因此,摆脱acc
,然后将其旋转
So, get rid of acc
, and turn this
go(outer, inner + 1, Stream[Long](outer * inner) ++ acc)
进入此
(outer * inner) #:: go(outer, inner + 1)
或类似的东西–您可能需要做一些探索,以了解如何确保您不严格评估递归调用.
or something similar -- you might have to do a little exploring to find out how to ensure you don't evaluate the recursive calls strictly.
这篇关于创建3位数字产品流时出现内存不足异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!