You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java/Kotlin中忽略各类变音符号的文本排序与搜索方案

多语言变音符号处理:排序与搜索的兼容方案

背景

多种语言中存在「变音符号(Diacritics)」,这类特殊符号附着在普通字母上,可能改变字母发音,或仅提供发音提示。

问题

使用基础方法对字符串排序和搜索时,会基于字符的Unicode值处理,导致排序顺序异常或搜索不到目标内容。搜索需定位目标字符串在文本中的出现位置,例如法语字符串「Le Garçon」中搜索「rc」,需匹配到「r」到「ç」的位置以实现高亮显示。

已尝试方案

  • 排序:借助Collator和CollationKey实现
  • 搜索:使用Normalizer替换带变音符号的字母

但上述方案无法覆盖部分语言,比如希伯来语的Niqqud(类似英语元音的可选符号,作为Unicode字符附加在字母后,但显示在字母内部/周围)。对希伯来语文本做归一化处理无效,导致排序和搜索出现问题,示例代码如下:

val regex = Pattern.compile("[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+").toRegex()
val string = "בְּרֵאשִׁית"
val length = string.length // 长度为11,而非其他语言预期的6
val normalized = Normalizer.normalize(string, Normalizer.Form.NFD)
val result = normalized.replace(regex, "") // 结果与原字符串一致,未变为「בראשית」

有建议称ICU4J库可解决排序和搜索问题,但未找到相关使用方法。

疑问

  1. Java/Kotlin API中是否有更优的多语言兼容方案,可忽略变音符号进行排序和搜索?
  2. ICU4J能否解决该问题?若可以,在Java/Kotlin中如何使用?

疑问解答

1. Java/Kotlin 原生API的优化方案

Java/Kotlin原生的Collator支持通过调整强度忽略变音符号,针对希伯来语这类场景,可将Collator的强度设置为Collator.PRIMARY,此时会仅关注基础字符,忽略变音差异:

val collator = Collator.getInstance(Locale("he", "IL")) // 指定希伯来语区域
collator.strength = Collator.PRIMARY
// 排序示例
val list = listOf("בְּרֵאשִׁית", "בראשית")
list.sortedWith(collator) // 两个字符串会被判定为相等,排序时归为同一组

但原生Normalizer无法处理希伯来语Niqqud,因为Niqqud的Unicode分类不属于常规组合变音标记范围,原生正则无法匹配。这种场景下原生API没有完美解决方案,需依赖第三方库。

2. ICU4J的解决方案及使用方法

ICU4J对多语言支持比原生API更全面,完全可以解决希伯来语Niqqud这类特殊变音符号的处理问题。

步骤1:引入依赖

在Gradle中添加ICU4J依赖(版本可按需选择最新版):

implementation 'com.ibm.icu:icu4j:74.1'
步骤2:忽略变音符号的搜索处理

使用ICU4J的Normalizer2可移除包括Niqqud在内的各类语言变音符号:

import com.ibm.icu.text.Normalizer2

val string = "בְּרֵאשִׁית"
// 获取用于移除变音符号的归一化器
val normalizer = Normalizer2.getNFKDInstance(null, Normalizer2.Mode.COMPOSE, Normalizer2.Option.REMOVE_UNICODE_32)
val stripped = normalizer.normalize(string)
println(stripped) // 输出「בראשית」,长度为6

若需要定位原字符串中的匹配位置以实现高亮,可结合ICU4J的BreakIterator,或通过映射原字符与处理后字符的位置关系实现。

步骤3:多语言兼容排序

ICU4J的Collator支持更精细的排序规则,设置强度为PRIMARY即可忽略变音符号:

import com.ibm.icu.text.Collator

val collator = Collator.getInstance(Locale("he", "IL"))
collator.strength = Collator.PRIMARY
val list = listOf("בְּרֵאשִׁית", "בראשית", "שלום")
val sortedList = list.sortedWith(collator)
// 排序结果按基础字符排序,忽略Niqqud差异

内容的提问来源于stack exchange,提问作者android developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 02:27:45