Listbuffer行为不直观......如何解决?

时间:2015-10-07 12:12:17

标签: scala indexoutofboundsexception listbuffer

我有--prefix=<install directory>并将其用作队列。

现在考虑以下代码:

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) 当然是相互排斥的我做了一次使用它们!)

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

我不明白为什么这些行会引发ArrayOutOfBoundsException

我该如何移除物品?

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

ArrayOutOfBoundsException

但当然这不起作用

1 个答案:

答案 0 :(得分:4)

你的问题是你在迭代它的值时正在改变一个可变集合。

for(a <- 0 until buildQueue.size)中,buildQueue.size的值会被评估一次,因为0 until buildQueue.size会创建一个不可变的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()执行时,它不会同时附加到队列中的,实际上可能会移除{{1}后添加的任何块}已经开始了。