String.compareTo 按码元比较,对人来说排出来的顺序往往不对。这篇用真实运行比较 String、忽略大小写与 Collator 的排序,看 strength、decomposition、中文与混排、CollationKey 的性能和自定义规则。
原始: [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, å, ä, ö] 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 个字符