title: Behavior of entrySet().removeIf in ConcurrentHashMap
body: <p>I would like to use ConcurrentHashMap to let one thread delete some items from the map periodically and other threads to put and get items from the map at the same time. </p>
  
  <p>I'm using <code>map.entrySet().removeIf(lambda)</code> in the removing thread. I'm wondering what assumptions I can make about its behavior. I can see that <code>removeIf</code> method uses iterator to go through elements in the map, check the given condition and then remove them if needed using <code>iterator.remove()</code>. </p>
  
  <p>Documentation gives some info about ConcurrentHashMap iterators behavior:</p>
  
  <blockquote>
    <p>Similarly, Iterators, Spliterators and Enumerations return elements
    reflecting the state of the hash table at some point at or since the
    creation of the iterator/enumeration.  hey do not throw ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time. </p>
  </blockquote>
  
  <p>As the whole <code>removeIf</code> call happens in one thread I can be sure that the iterator is not used by more than one thread at the time. Still I'm wondering if the course of events described below is possible: </p>
  
  <ol>
  <li>Map contains mapping: <code>'A'-&gt;0</code></li>
  <li>Deleting Thread starts executing <code>map.entrySet().removeIf(entry-&gt;entry.getValue()==0)</code> </li>
  <li>Deleting Thread calls <code>.iteratator()</code> inside <code>removeIf</code> call and gets the iterator reflecting the current state of the collection </li>
  <li>Another thread executes <code>map.put('A', 1)</code> </li>
  <li>Deleting thread  still sees <code>'A'-&gt;0</code> mapping (iterator reflects the old state) and because <code>0==0</code> is true it decides to remove A key from the map. </li>
  <li>The map now contains <code>'A'-&gt;1</code> but deleting thread saw the old value of <code>0</code> and the <code>'A' -&gt;1</code> entry is removed even though it shouldn't be. The map is empty. </li>
  </ol>
  
  <p>I can imagine that the behavior may be prevented by the implementation in many ways. For example: maybe iterators are not reflecting put/remove operations but are always reflecting value updates or maybe the remove method of the iterator checks if the whole mapping (both key and value) is still present in the map before calling remove on the key. I couldn't find info about any of those things happening and I'm wondering if there's something which makes that use case safe. </p>