4
Exception in thread "main" java.util.ConcurrentModificationException
Squash the PC dirties the room Violet. The room's state is now dirty
Lily the animal growls
The Animal Lily left the room and goes to Green through the west door.
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
        at java.util.HashMap$KeyIterator.next(HashMap.java:828)
        at homework5.Room.critReactRoomStateChange(Room.java:76)
        at homework5.PC.play(PC.java:121)
        at homework5.Main.main(Main.java:41)
Java Result: 1

That is the error I receive.

My method looks like

public void critReactRoomStateChange(String command, PC pc) {
    Creature temp = null;
    Iterator iterator = getCreatures().keySet().iterator();
    while (iterator.hasNext()) {
        String names = iterator.next().toString();
        if (!(getCreatures().get(names) instanceof PC)) {
            temp = getCreatures().get(names);
            if (temp != null) {
                temp.reactStateChange(command, pc);
                temp.checkNewRoom();
            }
        }
    }
} 

So what I understand is this means I'm changing the size of the iterator before it is finished and this is the error you get. This is true as one of the reactStateChange is for an object to be removed out of the hashMap. How do I do this safely so that when I remove something it lets the Iterator know ahead of time so I can avoid this error. Thanks in advance. If more details are needed I'd be glad to meet your requests.

Kirs Kringle
  • 849
  • 2
  • 11
  • 26
  • 1
    as a comment on the side: the calls to `getCreatures().get(...)` are not necessary. you already have the object you get. it is what `iterator.next()` returns... – subsub Apr 26 '11 at 19:01
  • Possible duplicate of [Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop](http://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re) – Raedwald Mar 28 '16 at 14:32

3 Answers3

8

The only safe way to remove an element from an underlying collection and continue the iteration is to use the remove() method of the Iterator. This removes the last element returned by the next() method of the Iterator.

In your case, it appears that this would require passing the Iterator to the method that performs the modification (or make it an instance field, like the Map object is already).

erickson
  • 265,237
  • 58
  • 395
  • 493
  • Ah, as I was waiting for the answer I got the idea to look up Iterator in the API and found what you just told me. I feel a little silly for asking now. Thanks as you did help me because I was putting the remove after instead of before and I was still getting the error. lol tyty – Kirs Kringle Apr 26 '11 at 18:59
1

You remove it using iterator.remove().

Robin
  • 24,062
  • 5
  • 49
  • 58
1

Another option is to use ConcurrentHashMap which doesn't have this issue. You can use this as a drop in replacement and you don't need to change the rest of the code.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130