Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What basic operations on a Map are permitted while iterating over it?

Tags:

java

iterator

Say I am iterating over a Map in Java... I am unclear about what I can to that Map while in the process of iterating over it. I guess I am mostly confused by this warning in the Javadoc for the Iterator interface remove method:

[...] The behavior of an iterator is unspecified if the underlying collection is modified while the iteration is in progress in any way other than by calling this method.

I know for sure that I can invoke the remove method without any issues. But while iterating over the Map collection, can I:

  1. Change the value associated with a key with the Map class put method (put with an existing key)?

  2. Add a new entry with the Map class put method (put with a new key)?

  3. Remove an entry with the Map class remove method?

My guess is that I can probably safely do #1 (put to an existing key) but not safely do #2 or #3.

Thanks in advance for any clarification on this.

like image 218
Chris Markle Avatar asked Jan 29 '09 05:01

Chris Markle


2 Answers

You can use Iterator.remove(), and if using an entrySet iterator (of Map.Entry's) you can use Map.Entry.setValue(). Anything else and all bets are off - you should not change the map directly, and some maps will not permit either or both of the aforementioned methods.

Specifically, your (1), (2) and (3) are not permitted.

You might get away with setting an existing key's value through the Map object, but the Set.iterator() documentation specifically precludes that and it will be implementation specific:

If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation, or through the setValue operation on a map entry returned by the iterator) the results of the iteration are undefined. (emphasis added)

like image 147
Lawrence Dol Avatar answered Oct 08 '22 08:10

Lawrence Dol


If you take a look at the HashMap class, you'll see a field called 'modCount'. This is how the map knows when it's been modified during iteration. Any method that increments modCount when you're iterating will cause it to throw a ConcurrentModificationException.

That said, you CAN put a value into a map if the key already exists, effectively updating the entry with the new value:

 Map<String, Object> test = new HashMap<String, Object>();
 test.put("test", 1);

 for(String key : test.keySet())
 {
     test.put(key, 2); // this works!
 }

 System.out.println(test); // will print "test->2"

When you ask if you can perform these operations 'safely,' you don't have to worry too much because HashMap is designed to throw that ConcurrentModificationException as soon as it runs into a problem like this. These operations will fail fast; they won't leave the map in a bad state.

like image 36
Outlaw Programmer Avatar answered Oct 08 '22 07:10

Outlaw Programmer