Kotlin / kotlinx.collections.immutable

Immutable persistent collections for Kotlin

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

java.util.ConcurrentModificationException in PersistentMap.mutate {}

AbelToy opened this issue · comments

Using put multiple times in PersistentMap.mutate block results in java.util.ConcurrentModificationException.

Can be reproduced in 0.3.5 with the following code:

val initialData = Array(100) { i -> i to i * 2 }
val map = persistentMapOf(*initialData)

map.mutate {
    it.forEach { (key, value) -> it[key] = value }
}

That is rather expected: a mutable map cannot be mutated while it is iterated.

replaceAll causes the same issue…

The parameter of the mutate lambda is a mutable map, not the persistent map itself. The ‘it’ iterated by the forEach loop is the mutator, not the persistent map. So what you intend to do should work if you write ‘map.forEach’ instead of ‘it.forEach’

@fitermay I can confirm map.forEach works.

However, I am stumped as to why it.replaceAll causes a ConcurrentModificationException

            val items = listOf(1, 2, 3, 4, 5).toPersistentList()
            val changeItems = items.mutate {
                it.forEachIndexed { index, item ->
                    it[index] = item * 10
                }
            }
            println(changeItems)

Cause error:

Caused by: java.util.ConcurrentModificationException
                                                	at kotlinx.collections.immutable.implementations.immutableList.PersistentVectorMutableIterator.checkForComodification(PersistentVectorMutableIterator.kt:127)
14:53:20.035 AndroidRuntime                  E  	at kotlinx.collections.immutable.implementations.immutableList.PersistentVectorMutableIterator.next(PersistentVectorMutableIterator.kt:58)

I'm also bitten by this, using replaceAll on the mutator. It is not clear to me at all that this is unintended use of the mutator, if that is the case. Can you clarify if this is a user error or a bug?