Kotlin中基于正则的双列表值匹配代码性能优化咨询
代码优化咨询:提升产品选项匹配逻辑的运行速度
现有数据与实现
原始产品数据列表
data class InputProductData(val optionFamilyInput: String?, val optionCodeInput: String?, val optionDescriptionInput: String?) val inputProductData = mutableListOf( InputProductData("AAA", "111", "Chimney with red bricks"), InputProductData(null, "222", "Two wide windows in the main floor"), InputProductData("CCCC", null, "Beautiful door in green color"), InputProductData("DDDD", null, "House with area 120 square meters"), InputProductData(null, "555", "Old wood windows") )
定制化数据列表
data class CustomizingProductOption(val id: Int, val optionName: String, val optionCategory: String, val optionFamily: String?, val optionCode: String?, val searchPattern: String?, val outputValue: String) val customizingProductOptions = mutableListOf( CustomizingProductOption(10001, "Chimney", "Additional options", "^AAA$", "", "^Chimney with", "Available"), CustomizingProductOption(10002, "Windows", "Basic options", "", "^222$", "^Two wide windows", "Available"), CustomizingProductOption(10002, "Windows", "Basic options", "", "^555$", "wood windows$", "Available"), CustomizingProductOption(10003, "Door color", "Basic options", "^CCCC$", "", "door in green color$", "green"), CustomizingProductOption(10004, "House area", "Basic options", "^DDD", "", "120 square meters", "120") )
当前匹配实现
通过嵌套循环实现两种匹配逻辑:
- 选项族+选项描述正则匹配
- 选项码+选项描述正则匹配
data class IndicatedOptions(val id: Int, val output: String) val indicatedOptions: MutableList<IndicatedOptions> = mutableListOf() for (i in 0 until inputProductData.size) { for (k in 0 until customizingProductOptions.size) { if(inputProductData[i].optionFamilyInput.toString().contains(Regex(customizingProductOptions[k].optionFamily.toString())) == true && inputProductData[i].optionDescriptionInput.toString().contains(Regex(customizingProductOptions[k].searchPattern.toString())) == true || inputProductData[i].optionCodeInput.toString().contains(Regex(customizingProductOptions[k].optionCode.toString())) == true && inputProductData[i].optionDescriptionInput.toString().contains(Regex(customizingProductOptions[k].searchPattern.toString())) == true) { indicatedOptions.add(IndicatedOptions(customizingProductOptions[k].id, customizingProductOptions[k].outputValue)) } } } println("\n--- ALL INDICATED OPTIONS ---") indicatedOptions.forEach { println(it) } val indicatedOptionsUnique = indicatedOptions.distinct().sortedBy { it.id } println("\n--- UNIQUE INDICATED OPTIONS ---") indicatedOptionsUnique.forEach {println(it)}
优化方案
1. 预编译正则表达式
原代码每次循环都会重复创建Regex实例,这是核心性能损耗点。提前编译定制选项中的正则模式,避免重复开销:
// 创建预编译正则的包装类 data class PrecompiledCustomOption( val id: Int, val outputValue: String, val optionFamilyRegex: Regex?, val optionCodeRegex: Regex?, val searchPatternRegex: Regex? ) // 转换原有定制选项列表为预编译版本 val precompiledOptions = customizingProductOptions.map { PrecompiledCustomOption( id = it.id, outputValue = it.outputValue, optionFamilyRegex = it.optionFamily.takeIf { s -> s.isNotEmpty() }?.let { s -> Regex(s) }, optionCodeRegex = it.optionCode.takeIf { s -> s.isNotEmpty() }?.let { s -> Regex(s) }, searchPatternRegex = it.searchPattern.takeIf { s -> s.isNotEmpty() }?.let { s -> Regex(s) } ) }
2. 优化空值处理与匹配逻辑
原代码直接对null调用toString()会得到"null"字符串,可能引发错误匹配;同时提前提取输入数据的非空值,减少重复访问:
// 直接用Set去重,避免后续调用distinct() val indicatedOptions = mutableSetOf<IndicatedOptions>() for (input in inputProductData) { val family = input.optionFamilyInput val code = input.optionCodeInput val desc = input.optionDescriptionInput ?: continue // 描述为空直接跳过,无匹配可能 for (option in precompiledOptions) { // 描述不匹配直接跳过后续判断 val patternMatch = option.searchPatternRegex?.containsMatchIn(desc) ?: false if (!patternMatch) continue val familyMatch = family != null && option.optionFamilyRegex?.containsMatchIn(family) ?: false val codeMatch = code != null && option.optionCodeRegex?.containsMatchIn(code) ?: false if (familyMatch || codeMatch) { indicatedOptions.add(IndicatedOptions(option.id, option.outputValue)) } } } // 排序后输出 val sortedOptions = indicatedOptions.sortedBy { it.id } println("\n--- UNIQUE INDICATED OPTIONS ---") sortedOptions.forEach { println(it) }
3. 分组查询减少遍历次数
将输入数据按选项族、选项码分组,针对定制选项直接查找对应分组,避免全量嵌套遍历:
// 按选项族分组 val familyGrouped = inputProductData.filter { it.optionFamilyInput != null } .groupBy { it.optionFamilyInput } // 按选项码分组 val codeGrouped = inputProductData.filter { it.optionCodeInput != null } .groupBy { it.optionCodeInput } val indicatedOptions = mutableSetOf<IndicatedOptions>() for (option in precompiledOptions) { val patternRegex = option.searchPatternRegex ?: continue // 处理选项族匹配场景 option.optionFamilyRegex?.let { familyRegex -> familyGrouped.keys.forEach { family -> if (familyRegex.containsMatchIn(family)) { familyGrouped[family]?.forEach { input -> if (patternRegex.containsMatchIn(input.optionDescriptionInput ?: "")) { indicatedOptions.add(IndicatedOptions(option.id, option.outputValue)) } } } } } // 处理选项码匹配场景 option.optionCodeRegex?.let { codeRegex -> codeGrouped.keys.forEach { code -> if (codeRegex.containsMatchIn(code)) { codeGrouped[code]?.forEach { input -> if (patternRegex.containsMatchIn(input.optionDescriptionInput ?: "")) { indicatedOptions.add(IndicatedOptions(option.id, option.outputValue)) } } } } } } val sortedOptions = indicatedOptions.sortedBy { it.id }
4. 提前过滤无效定制选项
过滤掉无任何匹配规则(选项族、选项码、搜索模式全为空)的定制选项,减少循环次数:
val validPrecompiledOptions = precompiledOptions.filter { it.optionFamilyRegex != null || it.optionCodeRegex != null || it.searchPatternRegex != null }
内容的提问来源于stack exchange,提问作者Clipart - Designer
相关产品推荐
相关产品推荐

