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

前端 未结 4 972
既然无缘
既然无缘 2021-01-11 14:21

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

相关标签:
4条回答
  • 2021-01-11 14:53

    There is no global answer. The map interface let the choice to the users. Unfortunately, I think that all the implementations in the jdk use the fail-fast implementation (here is the definition of fail-fast, as it stated in the HashMap Javadoc):

    The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

    0 讨论(0)
  • 2021-01-11 14:58

    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)

    0 讨论(0)
  • 2021-01-11 15:12

    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.

    0 讨论(0)
  • 2021-01-11 15:18

    In general, if you want to change the Map while iterating over it, you should use one of the iterator's methods. I have not actually tested to see if #1 will will work, but the others definitely will not.

    0 讨论(0)
提交回复
热议问题