bigywater.tech
Java · 215

Collator:按语言规则比较文本

String.compareTo 按码元比较,对人来说排出来的顺序往往不对。这篇用真实运行比较 String、忽略大小写与 Collator 的排序,看 strength、decomposition、中文与混排、CollationKey 的性能和自定义规则。

36 字节
CollationKey("Äpfel").toByteArray() 的长度
97 / 23 ms
20000 个字符串:Collator.compare 与 CollationKey 排序
166
Collator.getAvailableLocales() 的数量(JDK 21)

自然顺序 与 Collator

实测 · 本机执行输出
  原始: [zebra, Apple, apple, banana, Äpfel, éclair, eclair, Zoo, Eagle]
  String 自然顺序(按 UTF-16 码元):   [Apple, Eagle, Zoo, apple, banana, eclair, zebra, Äpfel, éclair]
  String.CASE_INSENSITIVE_ORDER:      [Apple, apple, banana, Eagle, eclair, zebra, Zoo, Äpfel, éclair]
  Collator(Locale.ENGLISH):           [Äpfel, apple, Apple, banana, Eagle, eclair, éclair, zebra, Zoo]
  Collator(Locale.GERMAN):            [Äpfel, apple, Apple, banana, Eagle, eclair, éclair, zebra, Zoo]
  瑞典语对比 [zebra, å, ä, ö, a, z]:
    Locale.ENGLISH: [a, å, ä, ö, z, zebra]
    Locale(sv):     [a, z, zebra, å, ä, ö]

strength 与 decomposition

实测 · 本机执行输出
  compare("abc", "ABC"): PRIMARY=0 SECONDARY=0 TERTIARY=-1 IDENTICAL=-1
  compare("abc", "abç"): PRIMARY=0 SECONDARY=-1 TERTIARY=-1 IDENTICAL=-1
  compare("abc", "abc"): PRIMARY=0 SECONDARY=0 TERTIARY=0 IDENTICAL=0
  compare("résumé", "resume"): PRIMARY=0 SECONDARY=1 TERTIARY=1 IDENTICAL=1
  compare("é", "é"): PRIMARY=0 SECONDARY=0 TERTIARY=0 IDENTICAL=-1
  默认 strength = 2(TERTIARY=2),默认 decomposition = 0(NO_DECOMPOSITION=0,CANONICAL_DECOMPOSITION=1)
  IDENTICAL + NO_DECOMPOSITION:compare("e\u0301", "\u00e9") = -1
  IDENTICAL + CANONICAL_DECOMPOSITION:compare("e\u0301", "\u00e9") = 0
  TERTIARY + NO_DECOMPOSITION:compare("e\u0301", "\u00e9") = 0;两者的 equals = false

中文与混合文字

实测 · 本机执行输出
  原始: [张三, 李四, 王五, 阿里, 赵六, 陈七, 周八, 吴九]
  String 自然顺序(码元): [吴九, 周八, 张三, 李四, 王五, 赵六, 阿里, 陈七]
  Collator(Locale.CHINA):  [阿里, 陈七, 李四, 王五, 吴九, 张三, 赵六, 周八]
  Collator(zh-u-co-pinyin) 对象: RuleBasedCollator
  混排 [b, 中, A, a, é, 1, _, Z, あ, 한]:
    自然顺序:        [1, A, Z, _, a, b, é, あ, 中, 한]
    Collator(ROOT):  [_, 1, a, A, b, é, Z, あ, 中, 한]
    Collator(CHINA): [_, 1, a, A, b, é, Z, あ, 中, 한]
  Collator.getAvailableLocales() 共 166 个;含 zh_CN = true,含 sv = true
  Locale.CHINA 的 Collator 与 ROOT 对比 张三/李四/阿里 的排序是否相同:false

性能与自定义规则

实测 · 本机执行输出
  20000 个随机字符串,Locale.GERMAN:Collator.compare 直接排序中位 97 ms;先生成 CollationKey 再排序(含生成)中位 23 ms;String 自然顺序中位 4 ms
  两种方式排序结果一致:true
  CollationKey("Äpfel").toByteArray() 长度 = 36(源串 5 个字符)
  自定义规则让 ch 排在 c 之后(捷克语风格,在 c 后加 ch),排序 [cista, chata, dobry, cesta, hrad, ciste]:
    默认 ENGLISH: [cesta, chata, cista, ciste, dobry, hrad]
    自定义规则:   [cesta, cista, ciste, chata, dobry, hrad]
  RuleBasedCollator.getRules() 长度(英语默认)= 850 个字符

分步演示

Collator
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12,默认区域数据
    • 没有验证:ICU4J 的 Collator 与 JDK 自带实现的差异、数字串的自然排序(file2 与 file10)、其它语言(日语、韩语)的具体顺序、不同 JDK 版本区域数据的差别、CollationKey 的字节格式
    京ICP备2026067502号-1京公网安备11010502063487号