Kotlin如何高效替换%NAMEX%占位符为数组对应索引元素
Kotlin 字符串占位符替换优化方案
原有实现的问题
你当前的遍历替换逻辑存在几个明显的性能和适配性缺陷:
- 每处理一个索引就全量扫描一次完整字符串,时间复杂度为
O(n*m)(n为原字符串长度,m为names数组长度),当字符串较长、替换项较多时性能损耗明显 - 每次调用
replace都会生成新的字符串对象,替换次数越多,临时内存开销越大 - 仅支持个位数索引的占位符,遇到
%NAME10%这类多位数索引的占位符无法正常匹配 - 无边界容错,占位符索引超出数组长度时会直接保留原始占位符,无降级处理
优化实现方案
方案1:单次扫描实现(性能最优)
核心思路是仅遍历一次原字符串,边匹配占位符边拼接结果,时间复杂度稳定为O(n),性能不会随替换项数量增长下降:
private fun String.replaceWithNames(names: List<String>): String { // 预分配和原字符串等长的初始容量,减少StringBuilder扩容开销 val result = StringBuilder(length) var cursor = 0 while (cursor < length) { // 匹配占位符起始标识%NAME if (cursor <= length - 6 && substring(cursor, cursor + 5) == "%NAME") { val indexStart = cursor + 5 var indexEnd = indexStart // 查找占位符结束标记% while (indexEnd < length && this[indexEnd] != '%') { indexEnd++ } if (indexEnd < length) { // 提取索引值做替换 val targetIndex = substring(indexStart, indexEnd).toIntOrNull() if (targetIndex != null && targetIndex in names.indices) { result.append(names[targetIndex]) cursor = indexEnd + 1 continue } } } // 非占位符的普通字符直接追加 result.append(this[cursor]) cursor++ } return result.toString() }
这个实现的优势:
- 性能稳定,无论替换项有多少都只扫描一次原字符串
- 仅创建一个StringBuilder实例,无多余临时字符串开销
- 支持任意位数的数字索引占位符
- 自带容错,非法占位符、超范围索引都会原样保留,不会出现异常替换
方案2:正则替换实现(代码最简洁)
如果对极致性能没有要求,追求代码可读性和简洁度,可以用正则匹配替换,性能远好于循环全量替换的原始实现:
private fun String.replaceWithNames(names: List<String>): String { val placeholderRegex = Regex("%NAME(\\d+)%") return replace(placeholderRegex) { matchResult -> val index = matchResult.groupValues[1].toIntOrNull() // 索引合法就替换,否则保留原占位符 index?.takeIf { it in names.indices }?.let(names::get) ?: matchResult.value } }
内容的提问来源于stack exchange,提问作者Bresiu
相关产品推荐
相关产品推荐

