如何在MessageFormat中基于多条件实现更优的文本格式化?
优化MessageFormat多参数条件格式化的方案
针对多参数联合判断的格式化需求,仅用MessageFormat(含自定义规则)有几种更简洁的实现方式:
方案1:自定义多条件Format类
把多参数判断逻辑封装成自定义Format,避免嵌套plural的冗长写法。
实现示例:
import java.text.Format import java.text.ParsePosition import java.util.* // 自定义Format,接收多参数条件判断逻辑、匹配成功/失败的文本 class MultiConditionFormat( private val condition: (args: Array<Any?>) -> Boolean, private val trueText: String, private val falseText: String ) : Format() { override fun format(obj: Any?, toAppendTo: StringBuffer, pos: FieldPosition): StringBuffer { val args = obj as? Array<*> ?: return toAppendTo.append(falseText) return toAppendTo.append(if (condition(args as Array<Any?>)) trueText else falseText) } override fun parseObject(source: String?, pos: ParsePosition?): Any? { // 无需解析功能时可空实现 return null } } // 使用示例 fun main() { val formatStr = "{0}{1,multiCondition}{2}" val msgFormat = MessageFormat(formatStr, Locale.ENGLISH) // 注册自定义格式:判断第0、2位参数是否均非零 msgFormat.setFormatByArgumentIndex(1, MultiConditionFormat( condition = { args -> (args[0] as Int) != 0 && (args[2] as Int) != 0 }, trueText = " and ", falseText = "" )) // 测试场景 println(msgFormat.format(arrayOf(1, null, 20))) // 输出:1 and 20 println(msgFormat.format(arrayOf(0, null, 20))) // 输出:20 println(msgFormat.format(arrayOf(1, null, 0))) // 输出:1 println(msgFormat.format(arrayOf(0, null, 0))) // 输出: }
方案2:用复合参数简化逻辑
先把多参数条件转换成单一标记值,再用原生ChoiceFormat匹配结果,写法更简洁。
实现示例:
import java.text.ChoiceFormat import java.text.MessageFormat import java.util.* fun main() { // 生成复合标记:0=都为0,1=仅第一个非0,2=仅第二个非0,3=都非0 fun getCombinedFlag(hour: Int, minute: Int) = when { hour == 0 && minute == 0 -> 0 hour != 0 && minute == 0 -> 1 hour == 0 && minute != 0 -> 2 else -> 3 } val formatStr = "{0}{1,choice,0#|1#|2#|3# and }{2}" val msgFormat = MessageFormat(formatStr, Locale.ENGLISH) // 配置ChoiceFormat的匹配规则 val limits = doubleArrayOf(0.0, 1.0, 2.0, 3.0, 4.0) val texts = arrayOf("", "", "", " and ", "") msgFormat.setFormatByArgumentIndex(1, ChoiceFormat(limits, texts)) // 测试场景 println(msgFormat.format(arrayOf(1, getCombinedFlag(1,20), 20))) // 1 and 20 println(msgFormat.format(arrayOf(0, getCombinedFlag(0,20), 20))) // 20 }
这个方案无需自定义Format,原生API即可实现,扩展到第三个参数时,只需要新增复合标记的规则即可。
方案3:进阶:扩展MessageFormat模式语法
如果需要频繁使用多参数条件判断,可以自定义MessageFormat.PatternParser,扩展语法支持多参数联合表达式(比如你期望的{plural,0=0&1=0{} other{ and }})。但这种方式需要重写解析逻辑,复杂度较高,适合团队封装通用工具的场景。
内容的提问来源于stack exchange,提问作者Jonny
相关产品推荐
相关产品推荐

