首页 > 解决方案 > java.util.ConcurrentModificationException 在 kotlin 中替换字符串

问题描述

我在迭代器中得到并发异常替换字符串。

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)

标签: androidstringkotlincoroutinejava.util.concurrent

解决方案


Java Collection 类是快速失败的,这意味着如果在某个线程使用迭代器遍历它时更改 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,"")
}

推荐阅读