Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConcurrentModificationException in unmodifiable collection [duplicate]

I have this code below, and I'm getting a ConcurrentModificationException by executing the following line:

filterCardsToDevice(getCollection());

the code:

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

The stack is:

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)

Exactly on foreach line:

for (MyClass myObj : col) {

I don't see why this error occurs, because I'm not modifying the list.

like image 458
Pedro Estevao Avatar asked Nov 01 '13 11:11

Pedro Estevao


People also ask

How do you resolve ConcurrentModificationException?

How do you fix Java's ConcurrentModificationException? There are two basic approaches: Do not make any changes to a collection while an Iterator loops through it. If you can't stop the underlying collection from being modified during iteration, create a clone of the target data structure and iterate through the clone.

What causes ConcurrentModificationException?

What Causes ConcurrentModificationException. The ConcurrentModificationException generally occurs when working with Java Collections. The Collection classes in Java are very fail-fast and if they are attempted to be modified while a thread is iterating over it, a ConcurrentModificationException is thrown.

Can you get ConcurrentModificationException with a single thread?

From the said Exception's JavaDoc: “Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception.


1 Answers

Be aware, that Collections.unmodifiable* is not copying collection data, but only wrapping the original collection in a special wrapper. So if you modify the original collection, you can get this error.


If you want to create really independent unmodifiable collection instance:

Collections.unmodifiableCollection(new ArrayList<>(map.values()));
like image 179
Pavel Horal Avatar answered Oct 24 '22 10:10

Pavel Horal