Как удалить и добавить элементы в TreeMap во время итерации?

Я хочу написать такой код -

for (Map.Entry<Long, Integer> e : map.entrySet()){
    map.remove(k);
    map.put(x, value);
}

но я java.util.ConcurrentModificationException Я пытался использовать Iterator но я же Exception

5 ответов


объяснение, почему это вызвало ConcurrentModificationException

map.remove(k);
map.put(x, value);

для каждого цикла также внутренне создайте итератор entrySet of map. При итерации по карте вы изменили структуру карты, снова поместив значение на карту (map.put(x,value)), которые вызывают это ConcurrentModificationException.

это даже хорошо объясняется в документация -

итераторы, возвращаемые всем видом коллекции этого класса методы" являются сбоем быстро: если карта структурно изменены в любое время после создания итератора, кроме как через собственный метод удаления iterator, итератор будет бросать ConcurrentModificationException. Таким образом, при одновременном модификации, iterator перестал работать быстро и чисто, а не риск произвольного, недетерминированного поведения в неопределенное время в будущем.

как это решить -

вы должны измените структуру этой карты во время итерации, вы можете вставить эти значения позже, например, сохранить временную карту и добавить ее после завершения итерации.

Map<Long, Integer> tempMap = new HashMap<>();
for (Map.Entry<Long, Integer> e : map.entrySet()){
    map.remove(k);
    tempMap.put(x, value);
}
map.putApp(tempMap);

повторите копию, и вы можете добавить/удалить просто отлично:

for (Map.Entry<Long, Integer> e : new LinkedHashMap<Long, Integer>(map).entrySet()){
    map.remove(k);
    map.put(x, value);
}

это даже не больше строк кода, потому что копирование ims сделано в строке через конструктор копирования. LinkedHashMap был выбран для сохранения порядка итерации (если это имеет значение).


вам нужно будет создать копию вашей карты с помощью конструктора копирования. Теперь повторите на 1 и измените вторую карту. Я предполагаю, что вам не нужно будет повторять новую добавленную стоимость, поскольку это не будет иметь большого смысла.

вы можете выполнить свою задачу, создав копию, потому что ключи останутся одинаковыми в обоих.

EDIT:

Я не думаю, что это хорошая идея для итерации недавно добавленного элемента в Hashmap. Если вы проверяете api, предоставляемый Iterator, то вы найдет только метод remove, в нем нет метода add. Есть причина этого, и вы можете проверить javadoc для этого. Теперь перейдем к тому, как перебирать вновь добавленный элемент.

  1. Создать копию HashMap. Таким образом, вы будете повторять один и изменять другой Map.
  2. поскольку требование заключается в добавлении и удалении элементов в Map, Я хотел бы использовать ListIterator для этого [это отличается от нормального Iterator].
  3. I получите keyset из map1 и преобразовать его в список с помощью ArrayList(Collection<? extends E> c).
  4. теперь я получу ListIterator С List созданный на Шаге 3, и добавить, удалить элементы в ListIterator а также в Map2 [Remeber вам нужно добавить, удалить оба в ListIterator и Map2].

пример фрагмента кода для удаления элемента с карты приведен ниже.

for(Iterator<Map.Entry<Long, Integer>> it = map.entrySet().iterator();it.next();)
{
  Map.Entry<String, String> entry = it.next();
 if(//some logic)    
 it.remove();
}

Если ваш код включает в себя много добавления и удаления , вы можете просто использовать ConcurrentHashMap.ConcurrentHashMap


потому что вы не можете сделать это.

простое решение-использовать другую временную карту, где вы помещаете нужные значения и, наконец, переключаете указатели с исходным (i.E Map = newMap)