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