2013-11-01 18 views
8

tôi có mã này dưới đây, và tôi nhận được một ConcurrentModificationException bằng cách thực hiện dòng sau:ConcurrentModificationException trong bộ sưu tập unmodifiable

filterCardsToDevice(getCollection()); 

mã:

private List<MyClass> filterCardsToDevice(Collection<MyClass> col) { 
    final List<MyClass> newList = new ArrayList<MyClass>(); 

    for (MyClass myObj : col) { 
     long id = myObj.getId(); 
     if (id < 0 || id > 0xFFFFFFFFl) { 
      // just a log here 
     } else { 
      newList.add(myObj); 
     } 
    } 

    return newList; 
} 

private final Map<Long, MyClass> map = new HashMap<Long, MyClass>(); 

public Collection<MyClass> getCollection() { 
    synchronized (map) { 
     return Collections.unmodifiableCollection(map.values()); 
    } 
} 

Stack là:

at java.util.HashMap$HashIterator.nextEntry(HashMap.java:841)     
at java.util.HashMap$ValueIterator.next(HashMap.java:871)     
at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:1010) 

Chính xác trên đường truyền trực tuyến:

for (MyClass myObj : col) { 

Tôi không hiểu tại sao lỗi này xảy ra, bởi vì tôi không sửa đổi danh sách.

Trả lời

13

Xin lưu ý rằng Collections.unmodifiable*không sao chép dữ liệu thu thập, nhưng chỉ gói bộ sưu tập gốc vào một trình bao bọc đặc biệt. Vì vậy, nếu bạn sửa đổi bộ sưu tập gốc, bạn có thể gặp phải lỗi này.


Nếu bạn muốn tạo sự độc lập Ví dụ bộ sưu tập unmodifiable:

Collections.unmodifiableCollection(new ArrayList<>(map.values())); 
5

Bạn phải cập nhật các map trong chủ đề khác trong khi bạn đang iterating qua col. Cả hai chế độ xem map#valuesCollections.unmodifiableCollection trả về các cấu trúc dữ liệu hiện có, vì vậy những gì bạn đang lặp lại (và điều này được chứng kiến ​​bởi stacktrace của bạn) là tập hợp mục nhập của map.

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