OutOfMemory Exception when Creating Stream of 3 Digit Products

不打扰是莪最后的温柔 提交于 2019-12-12 02:18:29

问题


I wrote a function that produces a Stream[Long] consisting of the products of x-digit numbers.

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:

> 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

Using x = 2 works, but passing in x = 3 throws an OutOfMemory exception on outer = 668.

What is the cause of this exception?

When executing Stream[Long](outer * inner) ++ acc, is there some intermediate Stream that isn't getting properly garbage collected?


回答1:


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.

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.

So, get rid of acc, and turn this

go(outer, inner + 1, Stream[Long](outer * inner) ++ acc)

into this

(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.



来源:https://stackoverflow.com/questions/22593362/outofmemory-exception-when-creating-stream-of-3-digit-products

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!