使用Locale.SIMPLIFIED_CHINESE使用Collat​​or进行错误的排序

时间:2015-11-12 13:22:08

标签: java sorting character collation chinese-locale

我试图使用Locale.SIMPLIFIED_CHINESE订购中文国家/地区列表,这似乎是使用拼音(语音字母表,即根据拉丁语对应组合从A到Z排序的字符) 。

但是我发现了一些订单不好的情况。例如:

  • '中'字符是zhong1
  • '梵'字符是fan4

正确的顺序应该是梵<中,但相反,它是以其他方式订购的。

String[] characters = new String[] {"梵", "中"};
List<String> list = Arrays.asList(characters);
System.out.println("Before sorting...");
System.out.println(list.toString());

Collator collator = Collator.getInstance(Locale.SIMPLIFIED_CHINESE);
collator.setStrength(Collator.PRIMARY);
Collections.sort(list, collator);

System.out.println("After sorting...");
System.out.println(list.toString());

此代码段的结果是:

Before sorting...
[梵, 中]
After sorting...
[中, 梵]

进一步深入,我发现Java适用于Locale.SIMPLIFIED_CHINESE的规则。您可以在下一张图片中找到: https://postimg.cc/image/4t915a7gp/full/(注意梵在中后)

我在以红色突出显示的&lt;口&lt;口&lt;口&lt;口&lt;口之前意识到,所有字符都是根据他们的拉丁对应组合从A到Z排序的。但是,在&lt;之后口&lt;口&lt;口&lt;口&lt;口号,字符按字符的组成排序。例如,如果所有字符都具有相同的部分(通常是字符的左侧部分),则它们将组合在一起,而不是根据A到Z规则。

此外,&lt;口&lt;口&lt;口&lt;口&lt;口之后的所有字符都是不常见的汉字。因此,梵是一个不太常见的字符,因此它放在&lt;口&lt;口&lt;口&lt;口&lt;口。

之后。

我想知道为什么这个决定,如果它是故意的。但它会导致错误的排序。我不知道如何为此找到解决方案。

1 个答案:

答案 0 :(得分:2)

Java中的collat​​or提供的排序顺序基于写入该字符所需的笔划。

见下面的小片段来演示。从Wikitionary

取得的笔画数字
// the unicode character and the number of strokes
String[] characters = new String[]{
    "\u68B5 (11)", "\u4E2D (4)", 
    "\u5207 (4)", "\u5973 (3)", "\u898B (7)"
};
List<String> list = Arrays.asList(characters);
System.out.println("Before sorting...");
System.out.println(list.toString());

Collator collator = Collator.getInstance(Locale.TRADITIONAL_CHINESE);
collator.setStrength(Collator.PRIMARY);
System.out.println();
Collections.sort(list, collator);

System.out.println("After sorting...");
System.out.println(list.toString());

输出

Before sorting...
[梵 (11), 中 (4), 切 (4), 女 (3), 見 (7)]

After sorting...
[女 (3), 中 (4), 切 (4), 見 (7), 梵 (11)]

根据Unicode归类顺序,有一个增强请求JDK-6415666来实现排序顺序。但是关于Java 8 supported locale的信息,它没有在Java 8中实现。

修改使用icu4j中的整理器排序顺序

[梵 (11), 見 (7), 女 (3), 切 (4), 中 (4)]

ICU4J代码段

import com.ibm.icu.text.Collator;
import com.ibm.icu.text.RuleBasedCollator
...
Locale locale = new Locale("zh", "", "PINYIN");
Collator collator = (RuleBasedCollator) Collator.getInstance(locale);