how to avoid ConcurrentModificationException kotlin

I have a list of accounts, and when i make the long click, I want to remove the item from the arraylist. I'm trying to remove it from a alertdialog, but i'm getting the ConcurrentModificationException. This is where is crashing:

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

That's a common problem with the JVM, if you want to remove an item from a collection while iterating through it, you need to use the Iterators

exemple:

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

this will avoid ConcurrentModificationExceptions

I hope this answered your question, have a good day

Edit: you can find another explanation here, even if it is Java code the problem is the same
Edit n°2 the anwser of leonardkraemer show you a more kotlin-friendly way to do so


In Kotlin you can use removeIf{ predicate }. Which is a shorthand to using the Iterator. Full statement:

listAccounts.removeIf{ it == account.id }

for the explanation see Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop

Update: Kotlin-stdlib introduced removeAll { predicate } which, as Aguragorn pointed out in his answer, does the same and can be used if removeIf is not present on your runtime environment (i.e. Java 1.6 or Android pre API level 24).


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

Same solution as SeekDaSky but more Kotlin'y


It is actually removeAll { predicate } that kotlin stdlib introduced. So your code should look like this:

listAccounts.removeAll { it.id == idParamether }

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

Note: when coding in kotlin I prefer sticking to kotlin APIs, it avoids problems like "Call requires API level 24"


Try to use ConcurrentLinkedQueue instead of list to avoid this exception. As mentioned in ConcurrentLinkedQueue.Java, it orders elements FIFO (first-in-first-out).So it will avoid any problem with modifying a list while iterating it.
For exemple :

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)
    }
}

the out put is :

toto
titi