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 2014-10-17 05:23:03

回答

1

此異常可能由已檢測出的對象的併發修改時這種修改是不允許的方法被拋出。

下面的peice代碼是造成這個問題。

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所說的目標(兩者對我都沒有任何意義)。 OP的問題似乎想在'hm.get(1)'''''hello''字符串處追加'ArrayList' - 這個解決方案不適用。 – Jared 2014-10-17 07:56:23

1

問題您介紹的是在不修改HashMap,它的修改ArrayList在迭代它。 如果使用arListIterator,而不是使用增強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-each循環,如:對於-每個和迭代器之間

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

所以根本的不同,我們可以在使用唯一的迭代迭代修改集合。如果你得到一個集合的迭代器,然後再添加了它的一些更多的元素,然後遍歷集合將拋出此異常

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自己的remove或add方法之外,迭代器將拋出ConcurrentModificationException。因此,面對併發修改,迭代器快速而乾淨地失敗,而不是在將來某個未確定的時間冒着任意的,非確定性的行爲風險。 – kunal 2017-08-15 09:52:20

相關問題