0

Есть ли способ изменить значения HashMap определенного ключа при его повторении?Java - Исключение в потоке «main» java.util.ConcurrentModificationException

Пример программы приведен ниже: Метательное

public static void main(String[] args) { 
    HashMap<Integer,ArrayList<String>> hm = new HashMap<Integer, ArrayList<String>>();  
    ArrayList<String> ar = new ArrayList<String>(); 
    for(int i=0;i<50;i++){    
     ar.add(Integer.toString(i));    
    } 

    hm.put(1, ar);  

    for(String s:hm.get(1)){ 
     hm.get(1).add("hello"); 
    } 

} 

Ошибка:

Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source) 
    at java.util.ArrayList$Itr.next(Unknown Source) 
    at Excp.main(Excp.java:17) 
+0

Я не понимаю, что вы пытаетесь достичь. Цикл 'for' просто добавляет' 'hello" 'в' ArrayList' для каждой строки в нем ... не могли бы вы просто добавить 'ArrayList.size()' число '" hello "строк к этому' ArrayList '? Но я понятия не имею, почему вы хотели бы это сделать. – Jared

ответ

1

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

Ниже представлена ​​ошибка кода.

for(String s:hm.get(1)){ 
     hm.get(1).add("hello"); 
    } 

Вы повторяете и изменяете то же самое. Избежать этого путем создания new ArrayList

ArrayList<String> ar1 = new ArrayList<String>(); 

for (String s : hm.get(1)) { 
      ar1.add("hello"); 
     } 

имеет чтение here

+1

Я не вижу смысла в этом ответе, но на самом деле он не имитировал код, представленный OP. Это решение достигает совершенно иной цели, чем то, что заявлял ОП (ни один из них не имеет для меня никакого смысла). Вопрос OP, казалось, хотел бы добавить 'ArrayList' в' hm.get (1) 'с' "hello" 'строками, которые это решение не делает. – Jared

1

Проблемы в коде вашего предъявленный не изменяя HashMap, это изменение ArrayList в то время как итерации его. Вы можете избежать этого исключения, если вы используете ar «s ListIterator вместо того, чтобы использовать расширенный for цикл:

for (ListIterator<String> i = ar.listIterator(); i.hasNext(); i.next()) { 
    i.add("hello"); 
} 
0

Если попытаться изменить в то время как итерацию списка вы получите этот Exception.

for(String s:hm.get(1)){ // iterate 
    hm.get(1).add("hello");//modify 
} 

Обе операции влияют на hm

Вам не нужно повторять здесь. Просто используйте

hm.get(1).add("hello"); 
0

Если вы хотите добавить к оригинальнойArrayList, затем итерацию через него по своему усмотрению:

final ArrayList<String> arr = hm.get(1); 
final int size = arr.size(); 

// this will add size number of "hello" strings to ArrayList arr 
for(int i = 0; i < size; ++i){ 
    // you don't appear to ever use this value 
    final String s = arr.get(i); 

    // do something to arr 
    arr.add("hello"); 
} 
2

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

for(String str : stringList){ 
    stringList.add("Test"); 
} 

Итак, в приведенном выше примере мы получаем исключение во время выполнения.

Решение

Используйте итератор For-Каждый цикл, как:

static void filter(Collection<?> c) { 
    for (Iterator<?> it = c.iterator(); it.hasNext();) 
     if (!anyCondition(it.next())) 
      it.remove(); 
} 

Так принципиальной разницы между For-Каждый и итератора, мы можем изменить коллекцию в то время как итерация, используя только итератор.

0

Хотя не связан с вопросом, а просто добавить

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

Например:

package got; 

import java.util.*; 

public class GotCharacters { 


    public static void main(String... args){ 

     Person p1 = new Person("TL", 40, "Tyrion Lannister"); 
     Person p2 = new Person("JM", 50, "Jorah Mormont"); 
     Person p3 = new Person("AS", 20, "Arya Stark"); 

     //Defining the collection and adding some elements 
     ArrayList<Person> al; 
     al = new ArrayList<Person>(); 
     al.add(p1); 
     al.add(p2); 
     al.add(p3); 

     //Getting the iterator 
     Iterator<Person> itr = al.iterator(); 

     Royalty r1 = new Student("DT", 25, "Daenerys Targaryen", "DragonMother", "Targaryen"); 
     Royalty r2 = new Student("JS", 28, "Jon Snow", "Lord Commander", "Targaryen"); 
     Collection<Royalty> c = new ArrayList<Royalty>(); 
     c.add(s1); 
     c.add(s2); 

     //Adding more elements after getting the iterator 
     al.addAll(c); 

     while(itr.hasNext()){ 
      System.out.print(itr.next()); 
     } 
    } 
} 

Результат:

Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) 
    at java.util.ArrayList$Itr.next(ArrayList.java:851) 
    at myArrayList.ArrayList1.main(ArrayList1.java:34) 
+0

Также из документов oracle: Итераторы, возвращаемые методами итератора этого класса и listIterator этого класса, работают с ошибкой: если список изменяется в любое время после создания итератора, любым способом, кроме как с помощью собственных методов удаления или добавления Iterator, итератор будет вызывать исключение ConcurrentModificationException. Таким образом, перед лицом одновременной модификации итератор быстро и чисто, а не рискует произвольным, недетерминированным поведением в неопределенное время в будущем. – kunal

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