2013-03-05 72 views
6

我有一个字符串集合,需要对它进行排序。我正在使用Collat​​or。 但输出很奇怪。Collat​​or比较字符串怪异

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' 之后。我在这里错过了什么?

+0

为什么会 “1Z5800701A” 过来人 “1Z5800701B” 之后? – 2013-03-05 17:35:22

+2

我不这么说。我说1Z5800701B应该去1Z5800701A之后,因为B在A之后按字母顺序排列,不是吗? – Behnil 2013-03-05 17:47:25

+2

请记住,Collat​​or'执行区域设置敏感的字符串比较'。所以它不完全是char比较,而是特定于语言的比较。 – 2013-03-05 17:48:44

回答

5

这是使用的语言环境的问题,您可以使用LC_ALL=en_US sort在bash shell中重现相同的行为。问题在于,在这个区域中,“单词分隔符”与“单词字符”的处理方式不同(即不能总是说字符X在字符B之前或之后排序 - 它取决于上下文)。结果是如果你有1Z5800701 <optional separators> A,它在1Z5800701 <optional separators> B之前排序,这就是为什么1Z5800701B出现在A位于数字之后的所有组合之后,可选用“分隔符”分隔。您还可以看到“并不明显”排序一些例子中this Wikipedia articles

+1

你基本上说 - 它是语言环境敏感的,这是一个事实。但我想知道规则。为什么像上面这样的命令? – Behnil 2013-03-05 19:38:34

+0

@Behnil在我的系统中,'en_US'语言环境继承了文件'/ usr/share/i18n/locales/iso14651_t1_common'中的所有排序规则,这是对整理规则的345 kB长文本描述。如果你能忍受,请查看[Unicode排序算法](http://www.unicode.org/reports/tr10/)。这非常复杂。有两种主要的[在排序时处理多字字符串的方法](http://en.wikipedia.org/wiki/Alphabetical_order#Treatment_of_multiword_strings),这里选择的方法是字边界不相关。 – 2013-03-05 21:37:49

+0

我接受你的答案,虽然我不完全满意。 1Z5800701A和1Z5800701B之间是另一个字符串的事实是不清楚的。 Collat​​or当时没用。 – Behnil 2013-03-06 09:11:02

0

这不是它的一个功能:)

java.text.Collator只有一个默认的实现中的错误; RuleBasedCollator,它忽略白色空格。

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

只是检查班级的校书郎的

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

即使你是对的,它忽略空格,然后顺序1Z5800701A, 1Z5800701A, 1Z5800701A, 1Z5800701A, 1Z5800701B仍然没有道理给我。我看不到任何规则。 – Behnil 2013-03-05 19:33:40

+0

RuleBasedCollat​​or.getRules() – 2013-03-06 08:51:26