2013-08-14 13 views
6
import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.ListIterator; 

public class MyList { 
    public static void main(String[] args) { 
     ArrayList<String> al = new ArrayList<String>(); 

     al.add("S1"); 
     al.add("S2"); 
     al.add("S3"); 
     al.add("S4"); 

     Iterator<String> lir = al.iterator(); 

     while (lir.hasNext()) { 
      System.out.println(lir.next()); 
     } 

     al.add(2, "inserted"); 

     while (lir.hasNext()) { 
      System.out.println(lir.next()); 
     } 
    } 
} 

La particolare pezzo di codice genera un errore:java.util.ConcurrentModificationException durante l'inserimento in ArrayList

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

Scommetto che posso trovare più di 10 duplicati in SO. –

risposta

3

Si sta modificando la Collezione e poi cercando di utilizzare lo stesso iteratore.

  1. ottenere l'insieme iteratore nuovo

    al.add(2, "inserted"); 
    Iterator<String> lirNew = al.iterator(); 
    while (lirNew.hasNext()) { 
    System.out.println(lirNew.next()); 
    } 
    
  2. o Usa ListIterator

    ArrayList<String> al = new ArrayList<String>(); 
    
    al.add("S1"); 
    al.add("S2"); 
    al.add("S3"); 
    al.add("S4"); 
    
    ListIterator<String> lir = al.listIterator(); 
    
    while (lir.hasNext()) { 
        System.out.println(lir.next()); 
    
    } 
    
    lir.add("insert"); 
    
    while (lir.hasNext()) { 
        System.out.println(lir.next()); 
    
    } 
    
6

Succede a causa della lista di array viene modificato dopo la creazione di Iterator.

The iterators returned by this ArrayList's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Documentation

Iterator<String> lir = al.iterator(); // Iterator created 

while (lir.hasNext()) 
    System.out.println(lir.next()); 
al.add(2, "inserted"); // List is modified here 
while (lir.hasNext()) 
    System.out.println(lir.next());// Again it try to access list 

Che cosa si dovrebbe fare qui creare nuovo oggetto iteratore dopo la modifica.

... 
al.add(2, "inserted"); 
lir = al.iterator(); 
while (lir.hasNext()) 
    System.out.println(lir.next()); 
0

Aggiungi oggetto a elenco, dopo l'istante dell'iterazione. Questo cambierà il valore di modCount nella classe interna AbstractList $ Itr.class. next() method of iterator chiamerà il metodo checkForComodification(), che lancia una ConcurrentModificationException. E questo è chiamato fail-fast.

//add in abstractList 
public void add(int index, E element) { 
    if (index<0 || index>size) 
     throw new IndexOutOfBoundsException(); 
    checkForComodification(); 
    l.add(index+offset, element); 
    expectedModCount = l.modCount; 
    size++; 
    modCount++; //modCount changed 
} 

In AbstractList $ Itr

int expectedModCount; 

public E next() { 
     checkForComodification(); // cause ConcurrentModificationException 
    try { 
    E next = get(cursor); 
    lastRet = cursor++; 
    return next; 
    } catch (IndexOutOfBoundsException e) { 
    checkForComodification(); 
    throw new NoSuchElementException(); 
    } 
} 

private void checkForComodification() { 
    if (l.modCount != expectedModCount) //modCount not equals to itr.expectedModCount 
     throw new ConcurrentModificationException(); 
} 

rifare questo codice dopo il componente aggiuntivo:

al.add(2, "inserted"); 
lir = al.iterator(); 
+0

yah ma perché questo accade quando ho limitato l'ambito dell'iteratore al ciclo while – user2681668

+0

Non è causato dall'ambito, ma dall'invocazione add(). Faresti meglio a leggere il codice sorgente jdk. – criszhao

Problemi correlati