0

Я пытаюсь удалить определенные записи из ConcurrentHashMap. Однако, так как это происходит в многопоточной среде, записи могут быть удалены и/или изменены во время выполнения итерации. Когда это произойдет, метод remove на итераторе удалит запись, даже если она была изменена с момента получения через next. Я построил пример программы для иллюстрации этого:Удаление из ConcurrentHashMap

ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>(); 

map.put("foo", "bar"); 
map.put("quz", "qaz"); 

CountDownLatch foundBar = new CountDownLatch(1); 
CountDownLatch doneModifying = new CountDownLatch(1); 
CountDownLatch doneIterating = new CountDownLatch(1); 

new Thread(() -> { 
    try { 
     Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); 
     while (it.hasNext()) { 
      Map.Entry<String, String> entry = it.next(); 
      if (entry.getValue().equals("bar")) { 
       foundBar.countDown(); 
       doneModifying.await(); 
       it.remove(); 
      } 
     } 
     doneIterating.countDown(); 
    } catch (InterruptedException e) { 
     throw new Error(e); 
    } 
}).start(); 

foundBar.await(); 
map.put("foo", "nob"); 
doneModifying.countDown(); 

doneIterating.await(); 
System.out.println(map); 

выход будет {quz=qaz}, а не как я ожидал {quz=qaz,foo=nob}. Мой вопрос: как мне достичь желаемого поведения? Является ли метод remove(key, value) на карте во время итерации правильным выбором?

ответ

0

Да, вы должны использовать два аргумента метода remove. Хотя прямая мутация коллекции во время итерации, как правило, плохо для большинства java-коллекций, ConcurrentHashMap позволяет это.

+0

Хорошо, спасибо. Я знал, что это была возможность, просто не уверен, что самый элегантный. – diesieben07