2015-10-07 67 views
1

我有一個ListBuffer[MyClass]並將其用作隊列。Listbuffer行爲不直觀...如何解決?

現在考慮下面的代碼:

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) 

,但當然,這並不工作

+0

你可以顯示'chunk.init()'的實現嗎? – ccheneson

+0

@ccheneson由於'chunk.init()'不會更改ListBuffer/Queue,所以省略了詳細信息。它有什麼關係? – Sorona

+0

我認爲'init'可以改變它裏面的隊列,但如果你說它不是,那很好。我相信Sascha Kolberg的解釋是正確的 – ccheneson

回答

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() 
} 

UPDATE:

正如Teolha指出你可能也只是做:

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

這是更短,可能更有效。

然而,它不會建立追加被執行,而同時在buildChunks()隊列,實際上可能會刪除foreach啓動後添加任何塊。

+0

使用的東西:'buildQueue.clear()'末(如此循環外),效率較低? – Sorona

+1

@Teolha可能存在併發問題。更新了我的答案。 –

+0

你不會? – Sorona