Listbuffer 行为不直观...如何解决?
Listbuffer behaviour unintuitive... how to solve?
我有一个 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)
如果使用它们都会产生 ArrayOutOfBoundsException
(当然是互斥的我没有同时使用它们!)
正如我所说(顾名思义)ListBuffer 用作队列,因此如果处理了一个项目,我想将其从列表中删除。
我不明白为什么这些行会抛出 ArrayOutOfBoundsException
那我应该如何删除项目?
如果你能让我理解这一点,我很乐意使用更漂亮的方法,例如:
val chunk: Chunk = buildQueue.remove(a)
但这当然行不通
你的问题是你在迭代它的值时改变了一个可变集合。
在 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()
执行时同时构建 chunks 附加到队列,实际上可能会删除foreach
启动后添加的任何块。
我有一个 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)
如果使用它们都会产生 ArrayOutOfBoundsException
(当然是互斥的我没有同时使用它们!)
正如我所说(顾名思义)ListBuffer 用作队列,因此如果处理了一个项目,我想将其从列表中删除。
我不明白为什么这些行会抛出 ArrayOutOfBoundsException
那我应该如何删除项目?
如果你能让我理解这一点,我很乐意使用更漂亮的方法,例如:
val chunk: Chunk = buildQueue.remove(a)
但这当然行不通
你的问题是你在迭代它的值时改变了一个可变集合。
在 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()
执行时同时构建 chunks 附加到队列,实际上可能会删除foreach
启动后添加的任何块。