2013-05-19 4 views
8

Я хочу написать код, как это -Как удалить и добавить элементы в TreeMap во время итерации?

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

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

+4

@ZouZou Я искал для этого google и нашел этот вопрос на первом месте. Google недостаточно, контент также нужен :-) – peterh

+0

Может ли u подключить код для итератора. Вышеприведенный код, безусловно, даст вам одновременное изменение Exception. Вы выполняете итерацию через набор ключей, а также изменяете карту одновременно. Это рецепт катастрофы. – SamDJava

+0

Добавлен ответ ниже с образцом кода. – SamDJava

ответ

7

Explaintion почему это вызвало ConcurrentModificationException

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

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

Это даже хорошо объяснен в documentation -

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

Как решить эту проблему -

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

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

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

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

EDIT:

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

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

нет Мне нужно перебирать эти новые значения новые добавленные значения будут больше, чем текущие , поэтому мне нужно итератировать их слишком –

+0

см. Мое редактирование. Используя новые шаги, вы можете выполнить добавление и удаление обоих. – Lokesh

0

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

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

+0

Мне нужно перебрать новые добавленные значения –

+0

, затем сделать цикл while и продолжать делать это, пока вы не закончите. – Ahmad

2

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

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

Это даже не какие-либо больше строк кода, так как копия ИМС производится в режиме онлайн с помощью конструктора копирования. LinkedHashMap был выбран для сохранения порядка итераций (если это имеет значение).

1

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

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

Смежные вопросы