Как удалить и добавить элементы в 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 для этого. Теперь перейдем к тому, как перебирать вновь добавленный элемент.
- Создать копию
HashMap
. Таким образом, вы будете повторять один и изменять другойMap
. - поскольку требование заключается в добавлении и удалении элементов в
Map
, Я хотел бы использоватьListIterator
для этого [это отличается от нормальногоIterator
]. - I получите
keyset
из map1 и преобразовать его в список с помощьюArrayList(Collection<? extends E> c)
. - теперь я получу
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)