java.util.ConcurrentModificationException 从数组列表中删除元素时,即使使用迭代器
Posted
技术标签:
【中文标题】java.util.ConcurrentModificationException 从数组列表中删除元素时,即使使用迭代器【英文标题】:java.util.ConcurrentModificationException when removing elements from arraylist even with iterators 【发布时间】:2021-03-01 12:15:55 【问题描述】:当满足特定条件时,我试图从两个数组列表中删除内容。但是当条件满足时,我得到并发修改错误。在互联网上搜索后,我看到了使用迭代器概念解决此问题的解决方案,但这也不起作用。
这是我尝试过的两种代码变体:[我的代码在 Kotlin 中]
第一个变体:删除后立即出错
var index = 0
for (snap: DataSnapshot in snaps)
if (snap.key == snapshot.key)
snaps.removeAt(index)
emailOfSenders.removeAt(index)
index++
第二个变体:如果数组列表中的项目少于 3 个,则有效,但如果项目是 3 个或多于 3 个,我会得到相同的错误
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++
错误日志:
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)
更多信息:我正在创建一个 snapchat 克隆应用程序,并且我正在使用 google 的 firebase,它一切正常,即在 firebase 中上传、加载、删除。所以我不认为这是一个火力基地问题
【问题讨论】:
它所在的场景,应该是匹配元素在列表中最后一个的情况。而使用迭代器,您只能使用 iterator.remove() 方法。 【参考方案1】:如果您使用iterator
迭代collection
,那么您只能使用迭代器的修改器方法修改collection
,如果您尝试使用集合的修改器方法(删除、设置等)修改集合然后@ 987654325@ throws ConcurrentModificationException
,这被称为迭代器的fail-fast property。
在你的情况下,你应该做iterator.remove()
而不是snaps.removeAt(index)
请注意iterator.remove
删除了迭代器返回的最后一个元素。所以为了移除一个元素,你必须先调用next()
方法。例如,假设您想删除第一个元素。要实现这一点,您必须执行以下操作。
iterator.next()
iterator.remove() // Removes the element returned by next
如果数组列表中的项目少于 3 个,但如果项目是 3个或超过3个我得到同样的错误
这是因为 ConcurrentModificationException
是由 next()
方法抛出的,并且因为在 1 或 2 个元素的情况下,它只被调用一次,在任何修改之前,所以你不会得到任何错误。在上述情况下,执行以下步骤:
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
【讨论】:
感谢您的详细解释:)。我终于明白我做错了什么。你的解决方案帮助了我。谢谢你:D以上是关于java.util.ConcurrentModificationException 从数组列表中删除元素时,即使使用迭代器的主要内容,如果未能解决你的问题,请参考以下文章