Skip to content
Advertisement

java.util.ConcurrentModificationException when removing elements from arraylist even with iterators

I’m trying to delete content from two arrayLists when a particular condition is satisfied. But when the condition satisfied I get Concurrent modification error. After searching on internet I saw the solution to fix this using the iterator concept but that also doesn’t work.

Here is the two code variations that I tried: [my code is in Kotlin]

1st variation: instantly get error after removing

        var index = 0
        for (snap: DataSnapshot in snaps){
            if (snap.key == snapshot.key){
                snaps.removeAt(index)
                emailOfSenders.removeAt(index)
            }

            index++
        }

2nd variation: works if the items are less than 3 in the arraylist, but if items are 3 or more than 3 I get the same error

        var index = 0

        val iter: Iterator<DataSnapshot> = snaps.iterator()
        while (iter.hasNext()) {
            val snap: DataSnapshot = iter.next()
            if (snap.key == snapshot.key){
                snaps.removeAt(index)
                emailOfSenders.removeAt(index)
            }

            index++
        }

Error log:

2020-11-18 13:52:32.829 18935-18935/com.rofy.snapyandroid E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.rofy.snapyandroid, PID: 18935
    java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.next(ArrayList.java:860)
        at com.rofy.snapyandroid.SnapsActivity$onCreate$1.onChildRemoved(SnapsActivity.kt:54)
        at com.google.firebase.database.core.ChildEventRegistration.fireEvent(ChildEventRegistration.java:88)
        at com.google.firebase.database.core.view.DataEvent.fire(DataEvent.java:63)
        at com.google.firebase.database.core.view.EventRaiser$1.run(EventRaiser.java:55)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

More info: I am creating a snapchat clone app and I’m using google’s firebase for it everything works perfectly i.e uploading,doenloading,deleting in the firebase. so i don’t think this is a firebase issue

Advertisement

Answer

If you are iterating over a collection using an iterator then you can only modify the collection using iterator’s mutator methods, if you try to modify the collection using collection’s mutator methods (remove,set etc) then iterator throws ConcurrentModificationException, this is known as fail-fast property of iterators.

in your case instead of doing snaps.removeAt(index), you should do iterator.remove()

Please note that iterator.remove removes the last element returned by the iterator. So in order to remove an element you have to call next() method first. For example lets say you wanted to remove first element. to achieve this you will have to do the following.

iterator.next()
iterator.remove() // Removes the element returned by next

works if the items are less than 3 in the arraylist, but if items are 3 or more than 3 I get the same error

This is because, the ConcurrentModificationException is thrown by next() method, and because in case of 1 or 2 elements it only gets called once, that to before any modification, so you don’t get any error. In above cases following steps are executed:

1. iterator.hasNext()      // returns true 
2. iterator.next()         // works fine, since we have not modified collection yet
3. snaps.removeAt(index)   // removes one element
4. iterator.hasNext()      // returns false as there is only one element in list
5. iterator.next           // this line is not executed and hence no error
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement