Java漢字ソート(2)ピンイン順

21034 ワード

1.はじめに
漢字を含む文字列のソート方法は、主に2つあります.
一つはピンインで、一つは筆画です.
ピンイン順のコンパレータ(Comparator)の実装方法について説明します.
作者:Jeff 2007年12月21日11:27最終更新日: 2007年12月21日12:38 著作権声明:任意に転載することができて、転載する時必ずハイパーリンクの形式で文章の原始の出所と作者の情報と本著作権声明を明記してください.  http://www.blogjava.net/jeff-lau/archive/2007/12/21/169257.html
2.ピンインのソート
ピンインにはいくつかの方法がありますが、その中で最も主要なのは中華人民共和国の中国語ピンインChinese Phoneticです.漢字の並べ替えには2種類あります.1つはゆとりがあり、ピンインで最もよく使われる漢字を並べ替えることができ、もう1つは厳格で、ピンインでほとんどの漢字を並べ替えることができます.
2.1ゆったりしたピンインソート
原理:漢字は一番早くGB 2312コードで、六千余りの漢字を収録して、ピンイン順に並べて、コードは連続しています.後にGBK符号化が出現し、GB 2312が拡張され、2万以上の漢字が得られ、かつGB 2312に対応している、すなわちGB 2312における漢字符号化はそのままGBKに移されている(GBK符号化における[B 0-D 7]領域).
この6000以上の漢字の順序だけに関心があれば、以下の方法で漢字のゆとりソートを実現することができます.
 1 /**
 2  * @author Jeff 
 3  * 
 4  * Copyright (c)        ,      。
 5  */
 6 
 7 package chinese.utility;
 8 
 9 import java.text.Collator;
10 import java.util.Comparator;
11 import java.util.Locale;
12 
13 public class PinyinSimpleComparator implements Comparator {
14     public int compare(String o1, String o2) {
15         return Collator.getInstance(Locale.CHINESE).compare(o1, o2);
16     }
17 }

「孫、孟、宋、尹、廖、張、徐、昆、曹、曽、怡」という漢字を並べ替えた結果、「曹、昆、廖、孟、宋、孫、徐、尹、曽、張、怡」となった.最後の 怡 問題があって、最後に並ぶべきではありません.
注意:このプログラムには2つの不足があります.
  • gb 2312の漢字符号化は連続しているため、新たに増加した漢字が既存のgb 2312符号化にピンイン順に挿入されることは不可能であるため、新たに増加した漢字はピンイン順に並べられていない.
  • 同音字比較の結果は0に等しくない.

  • 次のテストコードは証明できます. 
     1 /**
     2 * @author Jeff 
     3 * 
     4 * Copyright (c)        ,      。
     5 */
     6 
     7 /**
     8 *     ( )
     9 */
    10 @Test
    11 public void testNoneCommon() {
    12     Assert.assertTrue(comparator.compare(" ", " ") > 0); 
    13 }
    14 
    15 /**
    16 *    
    17 */
    18 @Test
    19 public void testSameSound() {
    20     Assert.assertTrue(comparator.compare(" ", " ") != 0); 
    21 }

    2.2厳格なピンインソート法
    ゆったりしたピンインの2点不足を解決するために,中国語のピンインの関数を実現することで解決できる.goolgeの下でsfにpinyin 4 jのプロジェクトがあるのを見て、この問題を解決することができて、pinyin 4 jのプロジェクトの住所は:http://pinyin4j.sourceforge.net/.
    実装コード:
     1 /**
     2  * @author Jeff 
     3  * 
     4  * Copyright (c)        ,      。
     5  */
     6 package chinese.utility;
     7 
     8 import java.util.Comparator;
     9 import net.sourceforge.pinyin4j.PinyinHelper;
    10 
    11 public class PinyinComparator implements Comparator {
    12 
    13     public int compare(String o1, String o2) {
    14 
    15         for (int i = 0; i < o1.length() && i < o2.length(); i++) {
    16 
    17             int codePoint1 = o1.charAt(i);
    18             int codePoint2 = o2.charAt(i);
    19 
    20             if (Character.isSupplementaryCodePoint(codePoint1)
    21                     || Character.isSupplementaryCodePoint(codePoint2)) {
    22                 i++;
    23             }
    24 
    25             if (codePoint1 != codePoint2) {
    26                 if (Character.isSupplementaryCodePoint(codePoint1)
    27                         || Character.isSupplementaryCodePoint(codePoint2)) {
    28                     return codePoint1 - codePoint2;
    29                 }
    30 
    31                 String pinyin1 = pinyin((char) codePoint1);
    32                 String pinyin2 = pinyin((char) codePoint2);
    33 
    34                 if (pinyin1 != null && pinyin2 != null) { //         
    35                     if (!pinyin1.equals(pinyin2)) {
    36                         return pinyin1.compareTo(pinyin2);
    37                     }
    38                 } else {
    39                     return codePoint1 - codePoint2;
    40                 }
    41             }
    42         }
    43         return o1.length() - o2.length();
    44     }
    45 
    46     /**
    47      *      ,           。    , return null。
    48      */
    49     private String pinyin(char c) {
    50         String[] pinyins = PinyinHelper.toHanyuPinyinStringArray(c);
    51         if (pinyins == null) {
    52             return null;
    53         }
    54         return pinyins[0];
    55     }
    56 }

    3.テスト
     1 /**
     2  * @author Jeff 
     3  * 
     4  * Copyright (c)        ,      。
     5  */
     6 package chinese.utility.test;
     7 
     8 import java.util.Comparator;
     9 
    10 import org.junit.Assert;
    11 import org.junit.Test;
    12 
    13 import chinese.utility.PinyinComparator;
    14 
    15 public class PinyinComparatorTest {
    16 
    17     private Comparator comparator = new PinyinComparator();
    18 
    19     /**
    20      *    
    21      */
    22     @Test
    23     public void testCommon() {
    24         Assert.assertTrue(comparator.compare(" ", " ") < 0);
    25     }
    26 
    27     /**
    28      *     
    29      */
    30     @Test
    31     public void testDifferentLength() {
    32         Assert.assertTrue(comparator.compare("    ", "     ") < 0);
    33     }
    34 
    35     /**
    36      *       
    37      */
    38     @Test
    39     public void testNoneChinese() {
    40         Assert.assertTrue(comparator.compare("a", " ") < 0);
    41         Assert.assertTrue(comparator.compare("1", " ") < 0);
    42     }
    43 
    44     /**
    45      *     ( )
    46      */
    47     @Test
    48     public void testNoneCommon() {
    49         Assert.assertTrue(comparator.compare(" ", " ") < 0);
    50     }
    51 
    52     /**
    53      *    
    54      */
    55     @Test
    56     public void testSameSound() {
    57         Assert.assertTrue(comparator.compare(" ", " ") == 0);
    58     }
    59 
    60     /**
    61      *    ( )
    62      */
    63     @Test
    64     public void testMultiSound() {
    65         Assert.assertTrue(comparator.compare("  ", "  ") > 0);
    66     }
    67 
    68 }

     
    このような厳格なピンインのソートには改善すべき点があり、上のテストコードの最後のテストを見ると、プログラムは文脈に基づいて多音字のピンインを判断することはなく、単純に多音字の最初のピンインを取るだけであることがわかります.
     
    転載先:https://www.cnblogs.com/sjjg/p/4928777.html