在所有语言中,有没有一种方法可以对字符串进行排序?

13

我有这样的代码。在法语和俄语中排序是正确的。我使用了Locale.US,它似乎是正确的。这个解决方案对所有语言都有效吗?它适用于其他语言吗?例如:中文,韩文,日文... 如果不行,有更好的解决方案吗?

public class CollationTest {
    public static void main(final String[] args) {
        final Collator collator = Collator.getInstance(Locale.US);
        final SortedSet<String> set = new TreeSet<String>(collator);

        set.add("abîmer");
        set.add("abîmé");
        set.add("aberrer");
        set.add("abhorrer");
        set.add("aberrance");
        set.add("abécédaire");
        set.add("abducteur");
        set.add("abdomen");

        set.add("государственно-монополистический");
        set.add("гостить");
        set.add("гостевой");
        set.add("гостеприимный");
        set.add("госпожа");
        set.add("госплан");
        set.add("господи");
        set.add("господа");

        for(final String s : set) {
            System.out.println(s);
        }
    }
}

更新:抱歉,我并不要求这个集合必须按顺序包含所有语言。我的意思是这个集合包含一种语言,并且在每种语言中正确排序。

public class CollationTest {
    public static void main(final String[] args) {
        final Collator collator = Collator.getInstance(Locale.US);
        final SortedSet<String> set = new TreeSet<String>(collator);

        // Sorting in French.
        set.clear();
        set.add("abîmer");
        set.add("abîmé");
        set.add("aberrer");
        set.add("abhorrer");
        set.add("aberrance");
        set.add("abécédaire");
        set.add("abducteur");
        set.add("abdomen");
        for(final String s : set) {
            System.out.println(s);
        }

        // Sorting in Russian.
        set.clear();
        set.add("государственно-монополистический");
        set.add("гостить");
        set.add("гостевой");
        set.add("гостеприимный");
        set.add("госпожа");
        set.add("госплан");
        set.add("господи");
        set.add("господа");
        for(final String s : set) {
            System.out.println(s);
        }
    }
}

4
我认为你不能有意义地定义跨语言单词的排序。 - Flexo
3
即使集合只包含一种语言,每次想要排序时仍然需要为Collator选择正确的 Locale - 一二三
英语将所有字母变体都按照该字母排序,因此Ä和Å被视为A。但在瑞典语中,Ä和Å是Z之后出现的唯一字母。 - Liggliluff
提醒大家“亚洲语言”并不是一概而论的。例如,韩语使用字母(类似于英语)并且有明确定义的排序方式。 - user3932000
3个回答

25

由于每种语言都有自己的字母顺序,因此您无法这样做。例如,

如您所述,俄语中的с字母与土耳其语有不同的顺序。

您应该始终使用排序器。我能建议您使用的是Collection API。

    //
    // Define a collator for German language
    //
    Collator collator = Collator.getInstance(Locale.GERMAN);

    //
    // Sort the list using Collator
    //
    Collections.sort(words, collator);

如需更多信息,请查看并按照此处所述 链接

此程序展示了使用两个不同的排序器对相同单词列表进行排序时可能发生的情况:

Collator fr_FRCollator = Collator.getInstance(new Locale("fr","FR"));

Collator en_USCollator = Collator.getInstance(new Locale("en","US"));

名为 sortStrings 的排序方法可以与任何 Collator 一起使用。请注意,sortStrings 方法调用 compare 方法:

 public static void sortStrings(Collator collator, 
                           String[] words) {
  String tmp;
     for (int i = 0; i < words.length; i++) {
        for (int j = i + 1; j < words.length; j++) { 
           if (collator.compare(words[i], words[j]) > 0) {
              tmp = words[i];
              words[i] = words[j];
              words[j] = tmp;
           }
         }
      }
 }

英文排序器(English Collator)按以下方式对单词进行排序:

peach péché pêche sin

根据法语的排序规则,上述列表排序错误。在法语中,péché应该在排序后跟随pêche。法语排序器(French Collator)可以正确地对单词数组进行排序,如下所示:

peach pêche péché sin


如果你和我一样,读了这个很棒的答案,但不确定如何实现它,那么请查看这个相关问题的答案 - https://dev59.com/m2oy5IYBdhLWcg3wnfUi#8433662 - Ben

10

即使你能准确地检测出所使用的语言,有用的排序顺序通常特定于某种语言+国家组合。即使在同一种语言+国家中,根据使用或某些自定义,排序也可能会有所不同。

然而,如果您需要对任意文本集进行排序,最好选择Unicode Collation Algorithm,它为任何Unicode文本定义了语言无关的排序。该算法是可定制的,但并不一定会给任何一个文化带来有意义的结果(跨文化更不可能)。

Java的排序类没有实现该算法,但在ICU的RuleBaseCollator中可用。


1
在Java中,您可以使用Locale("")来获取根语言环境(在Java 7中有一个Locale.ROOT常量)。此语言环境的Collator是UCA。 - Robert Muir

0
据我所知,汉语没有任何语序,日语可能有平假名或片假名的顺序,但在汉字中很难确定。但是在计算机科学中,所有内容都由数字表示,语言符号也一样。每个符号对应唯一的 UNICODE 编码。因此,这可能是您的解决方法,可以使用它们的 UNICODE 位置来排序单词。

3
汉字和日语的汉字可以通过部首和笔画数进行排序。 - 一二三

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接