如何在Groovy中用并行流处理两个Map?问题排查与优化
Groovy并行流处理Map的错误修复与优化方案
问题场景
我需要在Groovy中用并行流处理两个HashMap<Object, ArrayList>类型的mapA和mapB:遍历mapA的并行流,检查key是否存在于mapB中;若存在,则对比对应ArrayList里的两个固定元素。现有代码在forEach行触发了VerifyError,同时希望优化代码结构。
现有代码
def Map = [:].withDefault {key -> return []} // 填充两个Map def jsonSlurper = new JsonSlurper() while ((inputLine = reader.readLine()) != null) { if (inputLine.startsWith('{"k"')) { def json =jsonSlurper.parseText(inputLine) Map.put(json.key[3], [json.key[4],json.key[5]]) } } // 对比两个Map,检查key是否存在;若存在则对比mapA与mapB对应值的第0位、第1位元素 def compareDatastore = { mapA,mapB -> mapA.entrySet().parallelStream().with { **it.forEach(entry->{** if(mapB.containsKey(entry.getKey())){ if(entry.getValue().get(0)!=mapB.get(entry.getKey()).get(0) || entry.getValue().get(1)!=mapB.get(entry.getKey()).get(1)) println "noMatch" }else{ println "notFound" } }) } }
Map示例值
key=1245,value=[a,b] key=1234,value=[b,a]
触发的错误
Caught: java.lang.VerifyError: Bad local variable type Exception Details: Location: scripts/smething$_run_closure6$_closure8$_closure9.doCall(Ljava/lang/Object;)Ljava/lang/Object; @155: aload_3 Reason: Type top (current frame, locals[3]) is not assignable to reference type Current Frame:
修复与优化方案
1. 修复并行流语法错误
原代码中with操作符已经将流对象作为闭包上下文,不需要再用it引用流,直接调用forEach即可。这是触发VerifyError的核心原因。修改后的对比逻辑:
def compareDatastore = { mapA, mapB -> mapA.entrySet().parallelStream().forEach { entry -> def key = entry.key if (mapB.containsKey(key)) { def listA = entry.value def listB = mapB[key] if (listA[0] != listB[0] || listA[1] != listB[1]) { println "noMatch: key=$key, A=[${listA[0]},${listA[1]}], B=[${listB[0]},${listB[1]}]" } } else { println "notFound: key=$key" } } }
2. 代码结构优化
- 简化取值操作:用Groovy原生的
entry.key、map[key]替代Java风格的getKey()、get(),代码更简洁。 - 提升日志可读性:输出时携带具体key和元素值,方便快速定位不匹配的位置。
- 减少重复查找:提前将
entry.value和mapB[key]赋值给变量,避免重复计算。 - 增强类型安全:如果能确定key和元素的类型,建议给Map指定泛型,比如
Map<Long, List<String>> mapA = [:],避免隐式类型转换问题。
3. 填充Map的代码优化
修正变量命名规范,简化赋值逻辑:
def map = [:].withDefault { [] } // Groovy自动返回闭包最后一行,可省略return def jsonSlurper = new JsonSlurper() def inputLine while ((inputLine = reader.readLine()) != null) { if (inputLine.startsWith('{"k"')) { def json = jsonSlurper.parseText(inputLine) map[json.key[3]] = [json.key[4], json.key[5]] // 用[]操作符替代put方法 } }
4. 并行流注意事项
- 线程安全保障:并行流会多线程访问
mapB,如果对比过程中mapB会被修改,必须用ConcurrentHashMap替代普通HashMap。 - 输出有序性:多线程下
println会出现输出乱序,若需要有序结果,可先收集所有不匹配项,最后统一打印,或用同步块包裹输出逻辑。
内容的提问来源于stack exchange,提问作者deewreck
相关产品推荐
相关产品推荐

