创建3位数字产品流时出现内存不足异常 [英] OutOfMemory Exception when Creating Stream of 3 Digit Products

查看:80
本文介绍了创建3位数字产品流时出现内存不足异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个函数,该函数生成由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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆