java.util.ConcurrentModificationException при замене строки в kotlin

#android #string #kotlin #coroutine #java.util.concurrent

#Android #строка #котлин #сопрограмма #java.util.concurrent

Вопрос:

Я получаю параллельное исключение, заменяющее строку внутри итератора.

 fun replaceValuesInURLString(allFieldsValues: HashMap<String, UserSelectedData>, urlString: String): String {
        var result = urlString
        val iteratorValues = allFieldsValues.iterator()
        while(iteratorValues.hasNext()){
            val fieldValue = iteratorValues.next()
            val key = "$${fieldValue.key}$"
            result = result.replace(key, fieldValue.value.getDataForReg()?: "")
        }
        //Regex replace to remove query param value's which are not replaced by earlier code
        val cleanUpRegex = "(\$)(.*?)(\$)".toRegex()
        return cleanUpRegex.replace(result,"")
    }
 

Я получаю параллельное исключение в следующей строке приведенного выше метода.

 result = result.replace(key, fieldValue.value.getDataForReg()?: "")
 

трассировка стека

     java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextNode(HashMap.java:1441)
        at java.util.HashMap$EntryIterator.next(HashMap.java:1475)
        at java.util.HashMap$EntryIterator.next(HashMap.java:1475)
        at Validator$DefaultImpls.replaceValuesInURLString(Validator.kt:32)
        at replaceValuesInURLString(ProcessedRegField.kt:18)
        at Validator$validate$inlined$apply$lambda$1.invokeSuspend(Validator.kt:119)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
 

Комментарии:

1. Что именно находится в строке с номером 32 в Validator.kt ?

2.Вы меняете содержимое этого allFieldsValues HashMap где-то за пределами этой функции?

Ответ №1:

Классы Java Collection быстры в отказоустойчивости, что означает, что если коллекция будет изменена, пока какой-либо поток проходит по ней с помощью итератора, iterator.next() выдаст ConcurrentModificationException , вы можете избежать этого в своей функции.

 fun replaceValuesInURLString(allFieldsValues: HashMap<String, UserSelectedData>, urlString: String): String {
    var result = urlString
    val iteratorValues = allFieldsValues.keySet().iterator()
    while(iteratorValues.hasNext()){
        val fieldValue = iteratorValues.next()
        val key = "$${fieldValue.key}$"
        result = result.replace(key, fieldValue.value.getDataForReg()?: "")
    }
    //Regex replace to remove query param value's which are not replaced by earlier code
    val cleanUpRegex = "(\$)(.*?)(\$)".toRegex()
    return cleanUpRegex.replace(result,"")
}