kotlinx.collections.immutable icon indicating copy to clipboard operation
kotlinx.collections.immutable copied to clipboard

java.util.ConcurrentModificationException in PersistentMap.mutate {}

Open AbelToy opened this issue 1 year ago • 6 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 }
}

AbelToy avatar Jun 02 '23 03:06 AbelToy

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

ilya-g avatar Jun 02 '23 11:06 ilya-g

replaceAll causes the same issue…

AbelToy avatar Jun 02 '23 11:06 AbelToy

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 avatar Jun 03 '23 18:06 fitermay

@fitermay I can confirm map.forEach works.

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

AbelToy avatar Jun 05 '23 03:06 AbelToy

            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)

JajaComp avatar Nov 24 '23 11:11 JajaComp

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?

ajrouvoet avatar Jun 13 '24 12:06 ajrouvoet