Java国际化:整理程序-字符串排序

时间:2020-01-09 10:35:24  来源:igfitidea点击:

每种语言对于字符串和字母的排序方式都有其自己的规则。因此,仅使用String.compareTo()方法可能不适用于所有语言。

要根据某个Locale的规则对字符串集合进行排序,可以使用为该Locale创建的java.text.Collator实例。这是一个创建Collator的例子:

Locale   locale = Locale.UK;
Collator collator = Collator.getInstance(locale);

要使用" Collator"实例比较两个字符串,请调用" compare()"方法。 compare()方法返回一个int,其含义与String.compareTo()方法相同:

负数表示作为参数传递的第一个字符串应在排序顺序中早于作为参数传递的第二个字符串出现(第一个字符串"更小")。 0表示两个字符串具有相同的顺序,例如如果字符串相等。正数表示第一个字符串应比第二个字符串晚出现在排序后的顺序中(第一个字符串为"更大")。

这是我们使用Collator.compare()方法的方式:

Locale   locale = Locale.UK;
Collator collator = Collator.getInstance(locale);

int result = collator.compare("A", "B");

在上面的示例中,result变量将包含负数。根据英国字符串排序规则进行排序时,字符串" A"将出现在字符串" B"之前。

定制归类规则

可以使用" RuleBasedCollator"来自定义用于比较字符串的规则。这是一个简单的示例:

String rules = "< b < a";

RuleBasedCollator ruleBasedCollator =
        new RuleBasedCollator(rules);

int result = ruleBasedCollator.compare("a", "b");

System.out.println(result);

本示例的第一行定义了用于比较字符串字符的规则。上面的示例定义b在a之前。因此,上面示例的最后一行将打印出" 1"。其余字符使用实例化的" RuleBasedCollator"的默认顺序进行排序

分组字符

我们可以通过在规则字符串中用逗号分隔字符来对字符进行分组。这是将大写和小写字符组合在一起的示例:

String rules = "< c,C < b,B";

RuleBasedCollator ruleBasedCollator =
        new RuleBasedCollator(rules);

int result = ruleBasedCollator.compare("boss", "Carol");
System.out.println(result);

此示例的第一行定义了在比较字符串时,大写和小写的" C"都出现在大写和小写的" B"之前。

解释为一个字符的字符组合

我们可以指定在订购字符串时将某些字符组合解释为一个字符。这是一个例子:

String rules = "< ch < b < a < c";

RuleBasedCollator ruleBasedCollator =
        new RuleBasedCollator(rules);

int result = ruleBasedCollator.compare("boss", "carol");
System.out.println(result);

result = ruleBasedCollator.compare("boss", "charlie");
System.out.println(result);

此示例的第一行定义了在对字符串进行排序时,字符组合" ch"将被解释为一个字符。同样," ch"将在" b"之前发生,这又在" a"之前发生,又在" c"之前发生。

此代码输出的输出是:

-1
1

字符串" boss"将出现在字符串" carol"之前。但是,字符串" boss"要出现在" charlie"之后,因为根据示例第一行中指定的规则," ch"出现在" b"之前。

全规则语法

我们可以在RuleBasedCollator类中使用更多规则。我们可以在RuleBasedCollator JavaDoc中看到规则的完整规范。

使用CollationKey改善了性能

如果需要多次对相同的字符串进行排序和重新排序,则可以为每个字符串创建一个" CollationKey",然后根据该字符串而不是字符串进行排序。基于" CollationKey"的排序是使用按位比较完成的。这比" RuleBasedCollator"通常使用的按字符串比较要快。

创建CollationKey需要花费时间。如果只对字符串排序一次,则按原样使用RuleBasedCollator会更快。

这是一个如何创建CollationKey并使用它们对字符串进行排序的示例:

String rules = "< c,C < b,B < a,A";

RuleBasedCollator ruleBasedCollator =
        new RuleBasedCollator(rules);

CollationKey[] collationKeys = new CollationKey[3];

collationKeys[0] = ruleBasedCollator.getCollationKey("boss");
collationKeys[1] = ruleBasedCollator.getCollationKey("carol");
collationKeys[2] = ruleBasedCollator.getCollationKey("andy");

Arrays.sort(collationKeys);

for(CollationKey collationKey : collationKeys) {
    System.out.println(collationKey.getSourceString());
}

此代码输出的输出是:

carol
boss
andy

排序前规范化文本

在unicode中,某些字符可以多种方式表示。有些具有自己的字符以及可以表示它们的其他unicode字符的组合。当可以用多种方式表示字符时,对它们进行排序将变得更加困难。因此,我们应该在对文本进行排序或者对其进行搜索之前对其进行标准化。规范化文本可确保始终以搜索和排序友好的方式表示给定的unicde字符串。

我们可以使用java.text.Normalizer类的静态normalize()方法对字符串进行标准化。这是一个例子:

String normalizedText =
    Normalizer.normalize("Text to normalize",
        Normalizer.Form.NFD);

" normalize()"方法的第一个参数是要规范化的文本。任何CharSequence都可以使用。

第二个参数是将文本规范化到的规范化形式。规范化文本时,我们必须选择四种不同的规范化形式之一。当要对文本进行归一化以进行排序时,请确保将所有文本归一化为相同的归一化形式。我们可以从Oracle的Java Normalizer教程中看到这些形式的含义。