Search code examples
scalafor-looparraylistarraybuffer

How do I iterate over a Scala ArrayBuffer while some elements are removed?


I have some Scala code from a game that is intended to call the onInteract(gameData: GameData, player: Player) method on each instance of a GameObject in a mutable.ArrayBuffer, gameobjects. However, sometimes these GameObjects will remove themselves from the ArrayBuffer, using the code gameobjects -= this. Since this alters the ArrayBuffer, Scala throws a NullPointerException. The code could be considered similar to the following:

for (gameobject <- gameobjects) {
    if (/* some condition */) gameobjects -= gameobject
}

and would throw an exception whenever an object is removed.

How can I remedy this? I'd imagine an ArrayBuffer, or at least the for loop, is unsuitable here.


Solution

  • Although I can't reproduce the exception in scala 2.11.8 you can see that the result is not correct:

    import scala.collection.mutable.ArrayBuffer
    val a = ArrayBuffer(1, 2, 2, 3)
    
    for (x <- a) {
       if (x == 2) a-=x
    }
    
    // There's still a 2!
    a: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
    

    I suspect this happens since the array now has fewer elements that when you started iterating.

    A better, more scala approach, is to use filter (or filterNot):

    val a = ArrayBuffer(1, 2, 2, 3)
    a.filter { _ != 2 } // == ArrayBuffer(1, 3)