如何避免ConcurrentModificationException kotlin

时间:2018-04-25 22:06:37

标签: kotlin

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

listAccounts.forEachIndexed { index, account ->
            if (idParamether == account.id) {
                listAccounts.remove(account)
            }
        }

9 个答案:

答案 0 :(得分:8)

在Kotlin中,您可以使用removeIf{ predicate }。这是使用Iterator的简写。完整声明:

listAccounts.removeIf{ it == account.id }

有关说明,请参阅Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop

答案 1 :(得分:2)

    val iterator = updatedList?.iterator()
    iterator?.forEach {
        if(it.id == someObj.id) {
            oldSubscription = it
            iterator.remove()
        }
    }

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

答案 2 :(得分:2)

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

listAccounts.removeAll { it.id == idParamether }

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

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

答案 3 :(得分:1)

这是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()
    }
}

这将避免ConcurrentModificationExceptions

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

编辑:您可以找到另一个解释here,即使它是Java代码,问题也是相同的 编辑n°2 leonardkraemer的anwser向您展示了更加友好的kotlin方式

答案 4 :(得分:1)

请尝试使用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)
        }

    }

输出是:
托托 蒂蒂

答案 5 :(得分:1)

我想补充Ryan's answer。如果您想在迭代期间添加到列表中,而不仅仅是删除,则需要在集合上调用.listIterator()而不是.iterator()。然后,借助this interface,您还将拥有add方法。 完整的代码:

with(listAccounts.listIterator()) {
    forEach {
        if (it.id == someObj.id) {
            // do some stuff with it
            oldSubscription = it
            remove()
            add(obj)
        }
    }
}

注意:我知道OP只是想删除,但是标题更为笼统,如果在这种情况下也搜索添加,这也是您所遇到的问题。

答案 6 :(得分:0)

您可以在遍历列表之前制作一个副本。这是小列表的有效解决方案。例如,这就是他们在遍历侦听器之前通常在 Android 上执行的操作。

答案 7 :(得分:0)

解决这个问题最简单的方法就是在删除后添加“break”

for (i in accounts) {
                    if (nick == i.nick) {
                        print("Enter PIN: ")
                        var pin = scan.nextInt()
                        if (pin == i.pin) {
                            accounts.remove(i)
                            println("Account has been deleted successfully!")
                            break
                        }
                    }
                }

答案 8 :(得分:0)

我也遇到了这个问题,我只是通过克隆起始列表来解决它,所以我经历了这个过程并添加或删除了原始列表中的元素。

这段代码给了我一个例外:

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

}

所以只需将其替换为:

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

}