I have an object that is in an arraylist, called a PowerUp
. I want these to be clickable, and when they are clicked, they will be removed from the screen, and ultimately taken out of the arraylist. I have inserted the handler into the class HealthPack
, which in turn extends PowerUp
. I am trying to access the certain HealthPack
that was clicked on and remove it from that list. I keep getting either it not working correctly, or a ConcurrentModificationException
. Here is my code I am trying to work with:
for (int i = 0; i < ((SurvivalMode) m).getPowerUps().size(); i++) {
PowerUp p = ((SurvivalMode) m).getPowerUps().get(i);
if (p.equals(hp)) { // HealthPack hp = this;
((SurvivalMode) m).getPowerUps().remove(p);
addPoints();
}
}
This current code actually throws a ConcurrentModificationException
when I go to click on a HealthPack
when the list is both adding it, and another is iterating through it. I have tried synchronizing the methods that mess with the list, but it didn't help.
How would I keep my program from throwing a ConcurrentModificationException
if one method is trying to remove an element from the list while another one is either iterating through the list or one is adding or removing an element from the list?
EDIT:
Here is some additional code that actually modifies the arraylist for the items:
if (powerups.size() >= 15 || isPaused()) return;
int gen = random.nextInt(10);
if (gen == 0) {
powerups.add(new HealthPack(this));
addMouseListener(powerups.get(powerups.size() - 1).getMouseListener());
}
}
and some code that actually iterates through that list (which throws the ConcurrentModificationException
):
for (PowerUp p : powerups) p.update();
CURRENT METHOD:
Here is the current method that I have attempted to remove from the list on click, but it still doesn't work so well, as in it doesn't remove anything at all or it will remove the wrong one, and sometimes even calls the method for all of the other PowerUp
s in the list:
Iterator<PowerUp> iter = ((SurvivalMode) m).getPowerUps().iterator();
while (iter.hasNext()) {
PowerUp p = (HealthPack) iter.next();
if (p.equals(hp)) {
((SurvivalMode) m).getPowerUps().remove(p);
}
CellDefender.getSounds().play(SoundType.HEALTH_PACK);
break;
}
Update 2:
What I have recently done is actually copy the array list within another point, and it partially helps to reduce the errors (within my update method):
CopyOnWriteArrayList<PowerUp> cpowerups = new CopyOnWriteArrayList<PowerUp>();
for (int i = 0; i < powerups.size(); i++) {
cpowerups.add(powerups.get(i));
}
for (PowerUp p : cpowerups) p.update();
And I would like to ask one thing, is there a way to detect if a list is currently being modified, and if the list is being modified to break out of the loop?