【问题标题】:Collator compares strings weirdCollat​​or 比较奇怪的字符串
【发布时间】:2013-03-05 17:31:04
【问题描述】:

我有一个字符串集合,需要对其进行排序。我正在使用整理器。 但是输出很奇怪。

final Collator collator = Collator.getInstance(Locale.US);

List<String> data = new ArrayList<String>();

data.add("1Z5800701_AB");
data.add("1Z5800701_AC");
data.add("1Z5800701-A");
data.add("1Z5800701 A");
data.add("1Z5800701B");
data.add("1Z5800701A");
data.add("1Z5800701 - A");

Collections.sort(data, new Comparator<String>() {

    @Override
    public int compare(String o1, String o2) {
        return collator.compare(o1, o2);
    }
});

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

输出是:

1Z5800701_AB
1Z5800701_AC
1Z5800701A
1Z5800701 A
1Z5800701 - A
1Z5800701-A
1Z5800701B

最后一个字符串“1Z5800701B”应该在“1Z5800701A”之后。我在这里错过了什么?

【问题讨论】:

  • 为什么“1Z5800701A”会出现在“1Z5800701B”之后?
  • 我不这么说。我说 1Z5800701B 应该在 1Z5800701A 之后,因为 B 按字母顺序排在 A 之后,不是吗?
  • 记住 Collat​​or performs locale-sensitive String comparison。因此,它不完全是逐字符比较,而是特定于语言的比较。
  • 我知道,但为什么 1Z5800701B 是美国地区的最后一个?

标签: java sorting


【解决方案1】:

这是使用的语言环境的问题,您可以使用LC_ALL=en_US sort 在 bash shell 中重现相同的行为。关键是“单词分隔符”在此语言环境中与“单词字符”的处理方式不同(即,您不能总是说字符 X 在字符 B 之前或之后排序 - 这取决于上下文)。结果是,如果您有1Z5800701 &lt;optional separators&gt; A,它会排在1Z5800701 &lt;optional separators&gt; B 之前,这就是为什么1Z5800701B 出现在所有组合之后,而A 出现在数字之后,可选地由“分隔符”分隔。您还可以在this Wikipedia articles中看到更多“不明显”排序的示例

【讨论】:

  • 您基本上是说 - 它对区域设置敏感,这是事实。但我想知道规则。为什么是上面的顺序?
  • @Behnil 在我的系统上,en_US 语言环境从文件/usr/share/i18n/locales/iso14651_t1_common 继承所有排序规则,该文件是排序规则的 345 kB 长的文本描述。如果你能忍受的话,看看Unicode Collation Algorithm。这非常复杂。有两个主要的ways of handling multiword strings when sorting,这里选择了与单词边界不相关的方法。
  • 我接受你的回答,尽管我对它并不完全满意。 1Z5800701A 和 1Z5800701B 之间是另一个字符串的事实是模糊的。那么 Collat​​or 就没用了。
【解决方案2】:

这不是错误,而是功能:)

java.text.Collator 只有一个默认实现; RuleBasedCollator,它会忽略空格。

http://docs.oracle.com/javase/1.4.2/docs/api/java/text/RuleBasedCollator.html

只需检查您的 Collat​​or 的类

final Collator collator = Collator.getInstance(Locale.US);
System.out.println(collator.getClass().getName());

【讨论】:

  • 即使你是对的并且它忽略了空格,那么 1Z5800701A、1Z5800701A、1Z5800701-A、1Z5800701-A、1Z5800701B 的顺序对我来说仍然没有意义。我看不到任何规则。
  • RuleBasedCollat​​or.getRules()
猜你喜欢
  • 2011-09-18
  • 2011-04-07
  • 2011-05-06
  • 2014-10-22
  • 2019-10-26
  • 2011-09-13
  • 1970-01-01
  • 2021-09-07
  • 2012-02-24
相关资源
最近更新 更多