即使使用迭代器,从数组列表中删除元素时也会出现 java.util.ConcurrentModificationException

问题描述 投票:0回答:1

当满足特定条件时,我尝试从两个 arrayList 中删除内容。但是当条件满足时我得到并发修改错误。在互联网上搜索后,我看到了使用迭代器概念解决此问题的解决方案,但这也不起作用。

这是我尝试过的两种代码变体:[我的代码在 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 中上传、加载、删除。所以我不认为这是一个 firebase 问题

java android firebase android-studio kotlin
1个回答
11
投票

如果您使用

collection
迭代
iterator
那么您只能使用迭代器的 mutator 方法修改
collection
,如果您尝试使用集合的 mutator 方法(删除、设置等)修改集合,则
iterator
抛出
ConcurrentModificationException
,这被称为迭代器的 fail-fast property

在你的情况下,你应该做

snaps.removeAt(index)
而不是做
iterator.remove()

请注意,

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
© www.soinside.com 2019 - 2024. All rights reserved.