John Jiang

          a cup of Java, cheers!
          https://github.com/johnshajiang/blog

             :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
            131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
          字符串排序
              本文是Sun官方以Blog形式發布的Java核心技術竅門(JavaCoreTechTip)中的一個。我之前尚未關注過java.text.Collator類,看過Sorting Strings這個tip之后覺得有些意義,故翻譯在了此處,也希望對其它朋友有所助益。(2008.04.07最后更新)

              使用Java平臺進行字符串排序被認為是一件簡單的工作,但為國際市場開發程序時,則需要有更多的考慮。如果你陷入只關注英語的心態中,并認為你的程序會工作的很好,因為它所顯示的字符串從今往后都是一樣的,你可能認為一切都很正常。但一旦你有一位西班牙用戶,他希望能夠正常地對mañana進行排序,但如果你都是使用String類中缺省的compare方法去做排序,字符ñ將會跟在字符z之后,而在正常的西班牙語排序中,ñ應該在字符n和o之間。這就是java.text包的類Collator發揮作用的地方了。
          想像這樣的一組詞
          • first
          • mañana
          • man
          • many
          • maxi
          • next
          使用String類的默認排序機制,即它的compare()方法,排序的結果將會是:
          • first
          • man
          • many
          • maxi
          • mañana
          • next
              此處,mañana出現在maxi與next之間。而在西班牙語世界中,mañana應該出現在many和maxi之間, 因為在字母表中,字符ñ(讀作eñe)跟在n之后。當來了一個德語用戶,想用他們自己的變音符時,你就可以寫一個自己的定制排序規則來處理ñ, 否則一組使用façade的設計模式將會怎樣呢?你是否想讓façade出現在factory之前或之后呢?(關鍵是如同對c或其它字符那樣去處理ç的小寫變音符。)
              這就是類Collator能派上用場的地方了。類Collator用于對語言敏感的排序問題,并不會只基于它們的ASCII/Unicode字符去嘗試排序。 使用Collator要求你在完全應用它的特性之前要理解一個額外的屬性,即稱之為強度(Strength)的屬性。Collator的強度設置決定了在排序時如何使用強(或弱)匹配。 該屬性有4個可能的值:PRIMARY,SECONDARY,TERTIARY和IDENTICAL。具體是哪個強度在產生作用取決于語言環境。 典型地,會有如下的情況。按從后往前的順序,IDENTICAL強度表示能夠被進行相同的處理的字符必須是一致的。TERTIARY通常用于忽略大小寫差異。SECONDARY用于忽略變音符,如n和ñ。 PRIMARY與IDENTICAL相似也是基于字母之間差異,但是當處理控制字符和發音時還是有所不同。查看Collator的javadoc, 以獲取更多關于這些強度之間的差異及分解(Decomposition)模式規則的信息。
              為了使用Collator,你需要先得到它的一個實例。你既可以調用getInstance方法以得到一個針對默認語言環境的Collator對象, 也可以傳遞一個指定的Locale對象給getInstance方法以得到一個針對特定語言環境的Collator對象。例如,為了獲得針對一個西班牙語的 Collator對象,你應使用new Locale("es")去創建一個西班牙語的Locale對象,然后將它傳入getInstance方法中:
          Collator esCollator =
              Collator.getInstance(
          new Locale("es"));
              假設針對該語言環境的默認Collator強度,針對西班牙語的默認強度是SECONDARY已經足夠了。然后你將這個Collator對象如任一Comparator對象 那樣傳入Collections類的sort方法的比較規則參數中,以得到排序后的List對象。
          Collections.sort(list, esCollator);
          操作之前的單詞列表,你現在就會得到一個基于西班牙語字母表的恰當排序結果:
          • first
          • man
          • many
          • mañana
          • maxi
          • next
          如果你在上述Collator中換用US的Locale對象,由于ñ并不是US中本有的字母,所以mañana將會出現在man和many之間。
          這兒有一個簡潔的例子以顯示這些差異。 import java.awt.*;
          import java.text.*;
          import java.util.*;
          import java.util.List; // Explicit import required
          import javax.swing.*;
          public class Sort {
              
          public static void main(String args[]) {
                  Runnable runner 
          = new Runnable() {
                      
          public void run() {
                          String words[] 
          = {"first""mañana""man",
                              
          "many""maxi""next"};
                          List list 
          = Arrays.asList(words);
                          JFrame frame 
          = new JFrame("Sorting");
                          frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
                          Box box 
          = Box.createVerticalBox();
                          frame.setContentPane(box);
                          JLabel label 
          = new JLabel("Word List:");
                          box.add(label);
                          JTextArea textArea 
          = new JTextArea( list.toString());
                          box.add(textArea);
                          Collections.sort(list);
                          label 
          = new JLabel("Sorted Word List:");
                          box.add(label);
                          textArea 
          = new JTextArea(list.toString ());
                          box.add(textArea);
                          Collator esCollator 
          = Collator.getInstance(new Locale("es"));
                          Collections.sort(list, esCollator);
                          label 
          = new JLabel("Collated Word List:");
                          box.add(label);
                          textArea 
          = new JTextArea(list.toString());
                          box.add(textArea);
                          frame.setSize(
          400200);
                          frame.setVisible(
          true);
                      }
                  };
                  EventQueue.invokeLater (runner);
              }
          }

              最后還有一點兒關于語言排序規則的信息。通過調用getInstance方法而得到的Collator對象通常是支持特定語言的RuleBasedCollator實例。 你可使用RuleBasedCollator去定義你自己的排序順序。該類的Javadoc更完整地描述了這種規則的語法,但還是讓我們先假設你有一個4字符字母表, 并希望字母的順序是CAFE,而不是ACEF,你的規則看起來就像這樣:

          String rule =
              
          "< c, C < a, A < f, F < e, E";
          RuleBasedCollator collator 
          = new RuleBasedCollator(rule);
              上述規則通過展示不同字母的大小寫定義了特定的字母順序為cafe?,F在對單詞列表ace,cafe,ef和face使用新的規則進行排序, 排序結果的順序為cafe,ace,face和ef:
          import java.text.*;
          import java.util.*;

          public class Rule {
              
          public static void main(String args[]) throws ParseException {
                  String words[] 
          = {"ace""cafe""ef""face"};
                  String rule 
          ="< c, C < a, A < f, F < e, E";
                  RuleBasedCollator collator 
          = new RuleBasedCollator(rule);
                  List list 
          = Arrays.asList(words);
                  Collections.sort(list, collator);
                  System.out.println(list);
              }
          }
          在對上述代碼編譯并運行之后,你將看到使用新規則排序后的單詞:
          > javac Rule.java
          > java Rule
          [cafe, ace, face, ef]
              請以后閱讀Javadoc中更多的關于 規則語法的信息,再嘗試擴展字母表并處理不同的變音符。
              現在,當你為全世界開發 程序時,你的程序就能做出更好的準備以去適應本地用戶了。也要確保字符串在資源包中,如之前的一個竅門所展示的那樣:Earlier tip。(譯注:原文并沒有提供這個Earlier tip的正確鏈接地址。)
          posted on 2008-04-07 09:10 John Jiang 閱讀(4960) 評論(3)  編輯  收藏 所屬分類: JavaSEJava 、翻譯 、CoreJavaTechTips

          評論

          # re: 字符串排序(譯) 2008-04-07 09:34 BeanSoft
          是呀 其實 Java 的國際化和本地化還是考慮的比較全面的。  回復  更多評論
            

          # re: 字符串排序(譯) 2008-04-07 09:52 Sha Jiang
          不錯,目前Locale支持的語言和國家/地區已很廣泛了。
          對于國際化,應該是夠用了。
          http://www.loc.gov/standards/iso639-2/englangn.html
          http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html  回復  更多評論
            

          # re: 字符串排序(譯) 2009-10-22 16:35 luyeqm
          2000萬行字符串排序已經完成.

          請訪問:luyeqm.vip.sina.com  回復  更多評論
            

          主站蜘蛛池模板: 铜川市| 共和县| 徐水县| 临桂县| 当阳市| 开原市| 彭阳县| 郎溪县| 莎车县| 新巴尔虎左旗| 图木舒克市| 蒙城县| 仙桃市| 崇州市| 延安市| 呈贡县| 崇信县| 泾阳县| 石阡县| 泸溪县| 大田县| 黔东| 永平县| 什邡市| 宁海县| 区。| 周口市| 沭阳县| 清苑县| 开阳县| 蒙城县| 陆河县| 奇台县| 华容县| 新源县| 酉阳| 呼和浩特市| 道孚县| 彩票| 垣曲县| 溧水县|