如何避免ConcurrentModificationException kotlin

zas*_*saz 15 kotlin

我有一个帐户列表,当我进行长按时,我想从arraylist中删除该项目.我正在尝试从alertdialog中删除它,但我得到了ConcurrentModificationException.这是崩溃的地方:

listAccounts.forEachIndexed { index, account ->
            if (idParamether == account.id) {
                listAccounts.remove(account)
            }
        }
Run Code Online (Sandbox Code Playgroud)

leo*_*mer 13

在Kotlin你可以使用removeIf{ predicate }.这是使用的简写Iterator.完整声明:

listAccounts.removeIf{ it == account.id }
Run Code Online (Sandbox Code Playgroud)

有关解释,请参阅迭代集合,在循环中删除时避免使用ConcurrentModificationException

  • 不要忘记此调用需要API级别24 (6认同)

小智 9

尝试使用 ConcurrentLinkedQueue 而不是 list 来避免此异常。正如 ConcurrentLinkedQueue.Java 中提到的,它对元素进行 FIFO(先进先出)排序。因此,它将避免在迭代列表时修改列表的任何问题。
举个例子 :

val list = ConcurrentLinkedQueue<String>()
list.add("toto")
list.add("tata")
list.add("titi")
list.forEachIndexed { index, it ->
    if (index % 2 == 0) {
        list.remove("tata")
        System.out.println(it)
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

托托蒂蒂


小智 8

with(listAccounts.iterator()) {
    forEach {
        if (it.id == someObj.id) {
            // do some stuff with it
            oldSubscription = it
            remove()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

与SeekDaSky相同的解决方案,但更多Kotlin'y


See*_*Sky 6

这是JVM的常见问题,如果您要在迭代过程中从集合中删除项目,则需要使用Iterators

例子:

val myCollection = mutableListOf(1,2,3,4)
val iterator = myCollection.iterator()
while(iterator.hasNext()){
    val item = iterator.next()
    if(item == 3){
        iterator.remove()
    }
}
Run Code Online (Sandbox Code Playgroud)

这将避免ConcurrentModificationExceptions

希望这能回答您的问题,祝您有美好的一天

编辑:您可以在此处找到其他说明,即使它是Java代码,问题也相同。
编辑n°2 leonardkraemer的答案向您展示了一种更为科特林友好的方法


Agu*_*orn 6

实际上removeAll { predicate }是kotlin stdlib引入的。因此,您的代码应如下所示:

listAccounts.removeAll { it.id == idParamether }
Run Code Online (Sandbox Code Playgroud)

参见:https : //kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/remove-all.html

注意:使用Kotlin进行编码时,我更喜欢使用Kotlin API,这样可以避免出现“调用需要API级别24”之类的问题


Ada*_*anz 6

我也遇到了这个问题,我简单地通过克隆起始列表来解决它,所以我仔细检查并添加或删除原始列表中的元素。

这段代码给了我例外:

 for(account in listAccounts){
    ....
    listAccounts.add(anotherAccount)
    ....

}
Run Code Online (Sandbox Code Playgroud)

所以只需将其替换为:

val listAccountCloned = listAccounts.toMutableList()
 for(account in listAccountCloned){
    ....
    listAccounts.add(anotherAccount)
    ....

}

Run Code Online (Sandbox Code Playgroud)