#Avoiding ConcurrentModification Exception

1 messages · Page 1 of 1 (latest)

cedar idol
#

I have a set of GameObjects . The set is iterated through every game loop and GameObject#update is called on each object. The problem arises when, for example, the player tries to delete another entity. Removing the particular obj from the set obviously throws an exception. How do I avoid this.

fallow marlinBOT
#

<@&987246399047479336> please have a look, thanks.

#

Here is an AI assisted attempt to answer your question 🤖. Maybe it helps! In any case, a human is on the way 👍. To continue talking to the AI, you can use </chatgpt:1108714622413963314>.

#
TJ-Bot
I have a set of `GameObjects` . The set is iterated through every game loop and GameObject#update is called on each object. The problem arises when, for example, the player tries to delete another entity. Removing the particular obj from the set obviously

le, a GameObject is added or removed from the set while it is being iterated through. This can lead to a ConcurrentModificationException being thrown.

To avoid this exception, you can use an Iterator to iterate through the set instead of directly using a for-each loop. By using an Iterator, you can safely add or remove elements from the set during iteration without causing any issues.

Here's an example of how you can iterate through your set using an Iterator:

Set<GameObject> gameObjects = new HashSet<>();
Iterator<GameObject> iterator = gameObjects.iterator();
while (iterator.hasNext()) {
    GameObject gameObject = iterator.next();
    gameObject.update();
    
    // Add or remove objects safely
    if (/* some condition */) {
        iterator.remove(); // Remove current object
    }
    
    if (/* some other condition */) {
        gameObjects.add(new GameObject()); // Add new object
    }
}

By using an Iterator and its remove() method, you can avoid the ConcurrentModificationException and safely modify your set while iterating through it. Additionally, make sure to synchronize access to your set if it is being modified by multiple threads to prevent any concurrency issues.

fierce falcon
#

or index out of bounds?

cedar idol
#

conccurent

fierce falcon
#

sounds like youre using an enhanced for loop

#
for(GameObject obj : objs) {

}```
#

yeah?

cedar idol
#

no i am using an iterator

fierce falcon
#

remove the element using the iterator

cedar idol
#

the problem is that i am not removing the object in the loop exactly

cedar idol
#

Scene#update is called each game loop, the function loops through all the stored objects and updates them
I have a PlayerEntity which extends GameObject, the player clicks on a block and it needs to be removed from the scene's list

fierce falcon
#

so you are using an iterator to iterate through the collection. but then trying to remove from the collection directly?

fierce falcon
#

concurrentmod occurs when you try to remove while iterating

#

yeah, dont do that

#

theres a reason it fails

#

its referred to as a "fail-fast" iterator

#

its failing because it knows the operation you are doing is dangerous & can lead to bugs

#

so its failing before those bugs can occur

#

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException

#

(from the docs of ArrayList, although applies to other lists)

cedar idol
#

the iterator's remove function doesn't take any input tho, how do i specify which object i need to remove
Should i then iterate over the complete set again?

fierce falcon
#

you can only remove the current element using an iterator

#

there are hackish tricks you can do to get rid of the error, but at the cost of potential bugs

#

the problem is that the operation you're trying to perform isnt safe

#

if you remove from a collection directly, thats going to impact any iterators that currently exist

#

so you cant remove while the list is being iterated, unless you remove the current element, through the iterator

#

you gotta rethink your structure

#

basically, if you're iterating over a collection, you shouldnt be removing elements before or after

cedar idol
#

shouldn't this be a common problem for games?

fierce falcon
#

its a common problem in lots of environments

#

the solution is proper design. you're suggesting the "remove" code is nested, existing in other classes

#

your list shouldnt be that accessible

#

instead, the class that owns the list should provide ways to communicate changes, and the class that needs to remove something should communicate that with the class that owns the list

#

that way these kinds of situations are kept under control, by a single class

#

encapsulate the list

cedar idol
#

I am doing that, i think
the Scene class contains the list of objects, I call Scene.removeObject(object) .
The problem is, that object won't be the current element of the iterator
for example, the iterator is currently on the PlayerEntity, but the player tries to break a grass block, I have to remove the grass block from the list

#

maybe I could solve it for now by updating the player separately

fierce falcon
#

flag it for removal on the next update cycle

cedar idol
#

but it would cause issues later if i wanna do something more fancy

cedar idol
#

wow thank you that worked!!
I add the objects i need to remove into another set, and then contains check in the iterator and remove it

fierce falcon
#

since ArrayList is index-based, its iterator is also index based. by removing elements ahead of the current, you risk out of bounds type errors, NoEuchElementException

#

if you remove before the current element, the list will shift all the elements, once again messing up the indexing

#

so yeah, cant be doing that

#

glad you got it fixed up

cedar idol
#

do i need to close this thread

fierce falcon
#

you can, or itll auto-close after a while

#

if you wanted to do some investigation

cedar idol
#

yeah I understood why it's a problem to do what i was doing
just couldn't figure out the solution myself

#

anyways, thanks alot