2013-08-14 41 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()); 
     } 
    } 
} 

Các mảnh cụ thể của mã ném một lỗi:java.util.ConcurrentModificationException khi chèn trong 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

Tôi đặt cược tôi có thể tìm thấy hơn 10 bản sao trong SO. –

Trả lời

3

Bạn đang thay đổi bộ sưu tập và sau đó cố gắng sử dụng các iterator tương tự.

  1. Lấy sưu tập iterator lại

    al.add(2, "inserted"); 
    Iterator<String> lirNew = al.iterator(); 
    while (lirNew.hasNext()) { 
    System.out.println(lirNew.next()); 
    } 
    
  2. hoặc Sử dụng 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

Nó xảy ra do array list được sửa đổi sau khi tạo ra các 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 

Bạn nên làm gì đây tạo đối tượng iterator mới sau khi chỉnh sửa.

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

Bạn thêm đối tượng vào danh sách, sau khi trình vòng lặp được căn chỉnh. Điều này sẽ thay đổi giá trị của modCount trong lớp bên trong AbstractList $ Itr.class. next() phương thức của iterator sẽ gọi phương thức checkForComodification(), nó sẽ đưa ra một ConcurrentModificationException. Và điều này được gọi là thất bại nhanh.

//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 
} 

Trong 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(); 
} 

redo mã này sau khi add bạn:

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

nhưng tại sao điều này xảy ra khi tôi đã giới hạn phạm vi của trình vòng lặp trong khi vòng lặp – user2681668

+0

Nó không phải do phạm vi, mà là lệnh gọi add() của bạn. Bạn nên đọc mã nguồn jdk. – criszhao

Các vấn đề liên quan