1

我有一个ListBuffer[MyClass]并将其用作队列。

现在考虑以下代码:

private def buildChunks(): Unit =
{
    for(a <- 0 until buildQueue.size)
    {
      val chunk: Chunk = buildQueue(a)
      chunk.init()
    //  buildQueue -= chunk
    //  buildQueue.remove(a)
    }
}

我的理解问题归结为这两行:

buildQueue -= chunk
buildQueue.remove(a)

它们都产生一个ArrayOutOfBoundsExceptionif used (当然互斥我没有同时使用它们!)

正如我所说的(顾名思义),ListBuffer 用作队列,因此如果处理了一个项目,我想将其从列表中删除。

我不明白为什么这些行中的任何一行都会引发 ArrayOutOfBoundsException

那我应该如何删除一个项目呢?

如果您能让我理解这一点,我很乐意使用更漂亮的方法,例如:

val chunk: Chunk = buildQueue.remove(a)

但这当然行不通

4

1 回答 1

3

您的问题是您在迭代可变集合的值时正在更改它。

for(a <- 0 until buildQueue.size)value 中buildQueue.size被评估一次,因为0 until buildQueue.size创建了一个 immutable Seq[Int]

现在,如果您的列表缓冲区最初的大小为 5,而您删除了一个元素,它最终的大小将为 4。但是,您的循环将迭代直到索引 4,该索引不再存在于列表缓冲区中。

解决此问题的一种方法是使用递归函数:

private def buildChunks(): Unit = {
  @tailrec
  def buildHead(): Unit = {
    buildQueue.headOption match {
      case None ⇒
        () // end of recursion
      case Some(chunk) ⇒
        chunk.init()
        buildQueue -= chunk
        buildHead()
    }
  }

  buildHead()
}

更新:

正如Teolha所指出的,您也可以这样做:

private def buildChunks(): Unit = {
   buildQueue.foreach(_.init())
   buildQueue.clear()
}

这更短,可能更有效。

但是,它不会在执行时同时构建附加到队列的buildChunks(),实际上可能会删除foreach启动后添加的任何块。

于 2015-10-07T12:55:20.470 回答