Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用toStream时,中间列表是否有资格进行垃圾收集?_Scala_Stream_Garbage Collection - Fatal编程技术网

Scala 使用toStream时,中间列表是否有资格进行垃圾收集?

Scala 使用toStream时,中间列表是否有资格进行垃圾收集?,scala,stream,garbage-collection,Scala,Stream,Garbage Collection,假设我想创建一个列表[(Int,Int)]: 但是,如果我想创建一个流[(Int,Int)]呢 scala> (0 to 3).toList.zip(0 to 3).toStream res4: scala.collection.immutable.Stream[(Int, Int)] = Stream((0,0), ?) 是用于构建垃圾回收的 RES4的中间列表吗?< /P> < P>如果将列表作为包含列表的头+链接到尾部的对象,答案是肯定的。 根据消息来源,在创建的流中并没有输入列表

假设我想创建一个
列表[(Int,Int)]

但是,如果我想创建一个
流[(Int,Int)]

scala> (0 to 3).toList.zip(0 to 3).toStream
res4: scala.collection.immutable.Stream[(Int, Int)] = Stream((0,0), ?)

是用于构建垃圾回收的<代码> RES4的中间列表吗?< /P> < P>如果将列表作为包含列表的头+链接到尾部的对象,答案是肯定的。 根据消息来源,在创建的流中并没有输入列表的闭包,所以可以收集这个列表(实际上只是“:“case class”)。但列表的尾部(剩余的“:””链)在闭包(var-tlGen)中被捕获,直到您在流上迭代为止

override def toStream : Stream[A] =
    if (isEmpty) Stream.Empty
    else new Stream.Cons(head, tail.toStream)

final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A] {
    override def isEmpty = false
    override def head = hd
    @volatile private[this] var tlVal: Stream[A] = _
    @volatile private[this] var tlGen = tl _
    def tailDefined: Boolean = tlGen eq null
    override def tail: Stream[A] = {
      if (!tailDefined)
        synchronized {
          if (!tailDefined) {
            tlVal = tlGen()
            tlGen = null
          }
        }

      tlVal
    }
}

所以,当流完全迭代时,所有尾部都有资格收集

例如,让我们以List(1,2,3,4).toStream.foreach(=>{})为例:


为什么不从一个流而不是一个列表开始:
(0到3).toStream.zip((0到3))
我认为在实际情况下,第一个或第二个集合并没有生成-所以我们仍然有问题List.toStream或Stream.zip(\uz:List)。无论如何,集合的尾部(无论其实现如何)将被捕获,直到流被迭代(参见我的答案)。
override def toStream : Stream[A] =
    if (isEmpty) Stream.Empty
    else new Stream.Cons(head, tail.toStream)

final class Cons[+A](hd: A, tl: => Stream[A]) extends Stream[A] {
    override def isEmpty = false
    override def head = hd
    @volatile private[this] var tlVal: Stream[A] = _
    @volatile private[this] var tlGen = tl _
    def tailDefined: Boolean = tlGen eq null
    override def tail: Stream[A] = {
      if (!tailDefined)
        synchronized {
          if (!tailDefined) {
            tlVal = tlGen()
            tlGen = null
          }
        }

      tlVal
    }
}
stream iteration    captured tail     generated stream        eligible for GC
0                   List(2, 3, 4)     Stream(1, ?)            List(1, 2, 3, 4)
1                   List(3, 4)        Stream(1, 2, ?)         List(2, 3, 4)
2                   List(4)           Stream(1, 2, 3, ?)      List(3, 4)
3                   Nil               Stream(1, 2, 3, 4)      List(4)