2013-05-15 72 views
12

我最近意識到Java排序規則似乎忽略空格。Java排序規則忽略空間

我有以下術語的列表:

Amman Jost 
Ammann Heinrich 
Ammanner Josef 
Bär Walter 
Bare Werner 
Barr Burt 
Barraud Maurice 

與上面的順序反映了德國期望排序,即考慮空間分成帳戶相關聯。 然而,Java整理使用

Collator collator = Collator.getInstance(Locale.GERMANY); 
Collections.sort(values, collator); 

給了我下面的順序:

Amman Jost 
Ammanner Josef 
Ammann Heinrich 
Bare Werner 
Barraud Maurice 
Barr Burt 
Bär Walter 

上面的結果其實不是我所料,由於空間不考慮(看起來像描述的情況這裏:Wikipedia Alphabetical order)。

這是否意味着Java排序規則不適用於這種用例,或者我在這裏做錯了什麼?有沒有辦法讓Java整理空間感知?

我會很高興的任何意見或建議。

+0

參見:http://stackoverflow.com/questions/15230339/collat​​or-compares-strings-weird – assylias

回答

7

您可以自定義排序規則。嘗試查看源代碼以查看如何構建德語語言環境的Collat​​or,如this answer中所述。

然後根據您的需要進行調整。 tutorial給出了一個起點。但沒有必要做所有的工作,其他人已經做到了:看到這個blog post dealing with the exact same problem for Czech

上面鏈接的解決方案的實質是:

String rules = ((RuleBasedCollator) Collator.getInstance(Locale.GERMANY)).getRules(); 
RuleBasedCollator correctedCollator 
    = new RuleBasedCollator(rules.replaceAll("<'\u005f'", "<' '<'\u005f'")); 

這只是底線規則之前增加了空格字符的規則。

我承認我沒有親自測試過。

+1

感謝您的回答和有用的鏈接 更大的問題是,對於一個基於Web的應用程序,它應該由用戶區域設置進行整理,您需要增強潛在的許多區域設置 – jhasenbe

+0

然後你應該自己寫:看看我的建議是否可以幫助 – JonesV

+0

@jhasenbe是的,這並不令人滿意。你也許可以在任何具有相似規則的區域上進行相同的修改,但這可能是一種破解 –

0

如果由於某些原因您不能修改語言環境,那麼我會建議您自己寫一切。這裏有一些想法,但是這個代碼是不完整的,不工作:

  • 而不必字符串列表中,創建自己的對象,實現媲美:

    public class myString implements Comparable<myString> { 
        private String name; 
    
        public myString(String name) { 
         this.name = name; 
        } 
    } 
    
  • 然後你會需要實現(見一個例子here

    public int compareTo(myString compareMyString) { 
        ... 
    } 
    
  • 現在到了最棘手的部分:

    • 爲了比較你的字符串,你需要將它們分開(這將產生一個字符串數組)。例如:

      // Original String 
      "Barr Burt" 
      
      // Splitted String 
      [0]: "Barr" 
      [1]: "Burt" 
      
    • 您需要逐個比較單詞。創建一個類似這樣的函數(這是一個僞代碼:「this.words [i]」稱爲「this」的第i個單詞。名稱「)

      public int compareWords(myString compareMyString, int i) 
      { 
          if (this.words[i] < compareMyString.words[i]) 
           return -1; // "this" should come before "compareMyString" 
      
          if (this.words[i] > compareMyString.words[i]) 
           return 1; // "this" should come after "compareMyString" 
      
          if (this.words[i] == compareMyString.words[i]) 
           return compareWords(i+1); 
      } 
      
    • 然後compareTo

      public int compareTo(myString compareMyString) { 
          return compareWords(compareMyString, 0); 
      }