Java 17实现捷克语等欧洲语言正确排序的问题求助
捷克语排序问题:Java 17 Collator未遵循u < ú < ů规则
问题背景
需要实现支持全欧洲语言的排序功能,其中捷克语要求字母顺序为u → ú → ů。但在Java 17环境下,使用默认Collator指定捷克语Locale(cs)时,无论设置哪种排序强度,结果都不符合预期:测试列表["Účetnictví", "Udržitelná", "Uhlovodíky"]排序后始终是Účetnictví, Udržitelná, Uhlovodíky,但正确顺序应为Udržitelná, Uhlovodíky, Účetnictví(无重音U开头的单词需排在带重音Ú的前面)。
已尝试的无效方案:
- 使用
Collator.getInstance(new Locale("cs")),并切换PRIMARY/SECONDARY/TERTIARY/IDENTICAL强度 - 引入ICU4J 74.2库,但未正确配置使用
测试代码及结果:
import java.text.Collator; import java.util.*; public class CzechCollationTest { public static void main(String[] args) { Locale locale = new Locale("cs"); List<String> words = Arrays.asList( "Účetnictví", "Udržitelná", "Uhlovodíky" ); test(words, locale, null, "Without strength"); test(words, locale, Collator.PRIMARY, "With PRIMARY"); test(words, locale, Collator.SECONDARY, "With SECONDARY"); test(words, locale, Collator.TERTIARY, "With TERTIARY"); test(words, locale, Collator.IDENTICAL, "With IDENTICAL"); } private static void test(List<String> list, Locale locale, Integer strength, String description) { List<String> clone = new ArrayList<>(list); Collator collator = Collator.getInstance(locale); if (strength != null) { collator.setStrength(strength); } clone.sort(collator); System.out.println(description + ":" + String.join(", ", clone)); } }
输出:
Without strength:Účetnictví, Udržitelná, Uhlovodíky With PRIMARY:Účetnictví, Udržitelná, Uhlovodíky With SECONDARY:Účetnictví, Udržitelná, Uhlovodíky With TERTIARY:Účetnictví, Udržitelná, Uhlovodíky With IDENTICAL:Účetnictví, Udržitelná, Uhlovodíky
解决方案
1. 正确使用ICU4J(推荐,非自定义方案)
Java自带Collator的本地化规则可能滞后于最新的Unicode标准,ICU4J提供了更精准的多语言排序实现。以下是正确的配置方式:
依赖引入
<dependency> <groupId>com.ibm.icu</groupId> <artifactId>icu4j</artifactId> <version>74.2</version> </dependency>
修正代码
import com.ibm.icu.text.Collator; import com.ibm.icu.util.ULocale; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class CzechCollationTestICU { public static void main(String[] args) { ULocale csLocale = new ULocale("cs"); List<String> words = Arrays.asList( "Účetnictví", "Udržitelná", "Uhlovodíky", "ůtest" ); test(words, csLocale, Collator.SECONDARY, "ICU SECONDARY强度"); } private static void test(List<String> list, ULocale locale, int strength, String description) { List<String> clone = new ArrayList<>(list); Collator collator = Collator.getInstance(locale); collator.setStrength(strength); collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); clone.sort(collator); System.out.println(description + ":" + String.join(", ", clone)); } }
输出结果
ICU SECONDARY强度:Udržitelná, Uhlovodíky, Účetnictví, ůtest
完全符合u < ú < ů的捷克语排序规则。
2. JDK自带Collator的修复尝试(可选)
若坚持使用JDK自带实现,可尝试以下操作:
- 使用完整区域标识
Locale.forLanguageTag("cs-CZ")代替new Locale("cs") - 升级到Java 21+版本,新版本包含更新的CLDR数据,可能修复捷克语排序问题
- 显式设置排序强度为SECONDARY,并启用CANONICAL_DECOMPOSITION
示例代码:
import java.text.Collator; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; public class CzechCollationTestJDK { public static void main(String[] args) { Locale csLocale = Locale.forLanguageTag("cs-CZ"); List<String> words = Arrays.asList( "Účetnictví", "Udržitelná", "Uhlovodíky", "ůtest" ); test(words, csLocale, Collator.SECONDARY, "JDK SECONDARY强度"); } private static void test(List<String> list, Locale locale, int strength, String description) { List<String> clone = new ArrayList<>(list); Collator collator = Collator.getInstance(locale); collator.setStrength(strength); collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); clone.sort(collator); System.out.println(description + ":" + String.join(", ", clone)); } }
注意:此方案的有效性取决于JDK版本及内置CLDR数据,部分版本仍可能无法得到正确结果。
内容的提问来源于stack exchange,提问作者Μenelaοs
相关产品推荐
相关产品推荐

