Scala迭代器令人困惑

时间:2016-10-29 01:23:19

标签: scala iterator iteration

Click here to see the problem statement image

我非常努力地理解为什么迭代器的行为如此。我的意思是在表演一次之后

result = lines.filter(_.nonEmpty).map(_.toInt)

迭代器缓冲区覆盖了除最后一个元素之外的所有elemnets。

我的意思是如果在给出5次

之后我的输入文本文件中有5个元素
result = lines.filter(_.nonEmpty).map(_.toInt)

我的迭代器变空了。

非常感谢任何帮助....提前致谢

2 个答案:

答案 0 :(得分:5)

doc很清楚你必须在调用除next和hasNext之外的任何方法之后丢弃迭代器。

http://www.scala-lang.org/api/2.11.8/#scala.collection.Iterator

答案 1 :(得分:0)

som-snytt就在这里,但没有解释到底发生了什么。

转换迭代器时,需要保存转换结果并仅使用它。特别是,在迭代器上调用filter在内部缓冲它,它在原始迭代器上调用next并将其保存在head变量中。如果你在缓冲的东西上调用next,你得到4.如果你在原始迭代器上调用next,你得到8:你的第一个元素消失了。如果你改为写了:

var result = lines.filter(_.nonEmpty).map(_.toInt)
var result = result.filter(_.nonEmpty).map(_.toInt)
var result = result.filter(_.nonEmpty).map(_.toInt)

您可以根据需要多次重复最后一行,而迭代器不会变空,因为您始终在转换的迭代器上运行。

编辑:解决缓冲评论 - 这里是Iterator.filter的代码:

def filter(p: A => Boolean): Iterator[A] = new AbstractIterator[A] {
  private var hd: A = _
  private var hdDefined: Boolean = false

  def hasNext: Boolean = hdDefined || {
    do {
      if (!self.hasNext) return false
      hd = self.next()
    } while (!p(hd))
    hdDefined = true
    true
  }

  def next() = if (hasNext) { hdDefined = false; hd } else empty.next()
}

hdhdDefined变量执行与Iterator.buffered中使用的完全相同的缓冲。