2013-03-05 66 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