如何简化Kotlin中的when表达式?优化数字与字符分支逻辑
简化Kotlin代码中的when表达式
我希望简化这段Kotlin代码中的when表达式,尤其是char.isDigit()和char.isLetter()对应的分支逻辑,请问该如何操作?
原始处理代码
smoothInput.forEach { char -> when { char.isValidOperator() -> { output.push(char) } char.isDigit() -> { if (output.isNotEmpty() && output.last()!!.isNumeric()) output.addToLast(char) else output.push(char) } char.isLetter() -> { if (output.isNotEmpty() && output.last()!!.isValidVariableName()) output.addToLast(char) else output.push(char) } else -> { throw InvalidIdentifierException() } } }
补充定义代码
InputStack类
class InputStack : Stack<String> { override val storage = mutableListOf<String>() fun push(e: Char) = push(e.toString()) fun push(e: Operator) = push(e.toString()) fun addToLast(e: Char) { storage[storage.size - 1] += e.toString() } }
Stack接口
interface Stack<T> { val storage: MutableList<T> fun asString(): String = buildString { appendLine("----top----") storage.asReversed().forEach { appendLine(it) } appendLine("-----------") } fun push(element: T) = storage.add(element) fun pop(): T { if (storage.size == 0) throw EmptyStackException() return storage.removeAt(storage.size - 1) } fun isEmpty(): Boolean = storage.isEmpty() fun isNotEmpty(): Boolean = !isEmpty() fun last(): T? = storage.lastOrNull() fun forEach(action: (T) -> Unit) { for (element in storage) action(element) } }
简化方案
观察代码可知,char.isDigit()和char.isLetter()的分支逻辑高度重复,仅判断栈顶元素的条件不同。可通过封装重复逻辑、合并分支实现简化:
1. 封装通用处理函数
抽离重复的"判断栈顶条件→选择追加/推入"逻辑为独立函数:
private fun handleChar(output: InputStack, char: Char, isValidTop: (String) -> Boolean) { if (output.isNotEmpty() && isValidTop(output.last()!!)) { output.addToLast(char) } else { output.push(char) } }
2. 简化when表达式
复用上述函数,合并digit和letter分支:
smoothInput.forEach { char -> when { char.isValidOperator() -> output.push(char) char.isDigit() -> handleChar(output, char) { it.isNumeric() } char.isLetter() -> handleChar(output, char) { it.isValidVariableName() } else -> throw InvalidIdentifierException() } }
3. 扩展性优化(可选)
若后续可能新增更多字符类型判断,可通过映射表匹配处理逻辑,提升扩展性:
val charHandlers = mapOf( Char::isValidOperator to { output: InputStack, char: Char -> output.push(char) }, Char::isDigit to { output: InputStack, char: Char -> handleChar(output, char) { it.isNumeric() } }, Char::isLetter to { output: InputStack, char: Char -> handleChar(output, char) { it.isValidVariableName() } } ) smoothInput.forEach { char -> charHandlers.entries.find { it.key(char) }?.value?.invoke(output, char) ?: throw InvalidIdentifierException() }
说明
- 第一种方案保留原when表达式的可读性,同时消除重复代码,是最稳妥的选择。
- 第二种映射方案适合需频繁扩展字符类型判断的场景,代价是可读性略有下降,可按需选用。
内容的提问来源于stack exchange,提问作者halotukozak
相关产品推荐
相关产品推荐

