1. 程式人生 > >java 優先順序以特殊字元、數字、英文、漢字(且漢字部分以漢字首字母)順序排序

java 優先順序以特殊字元、數字、英文、漢字(且漢字部分以漢字首字母)順序排序

1,當我使用如下程式碼對其中的list進行排序時: 優先順序以特殊字元、數字、英文、漢字(且漢字部分以漢字首字母)順序排序

    @Test
    public void sortList(){
        List<String>list=Lists.newArrayList();
        list.add("好好");
        list.add("最好");
        list.add("啊");
        list.add("##");
        list.add("嗯嗯");
        list.add("--");
        list.add("*");
        list.add("--");
        list.add("可以");
        list.add("56");
        list.add("");
        list.add(" ");
        list.add("bbbb");
        list.add("acc");
        list.add("52");
        list.add("aaaa");

        Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA);
        list.sort((o1, o2) -> ((Collator) CHINA_COMPARE).compare(o1, o2));

        System.out.println(list.toString());
    }

輸出結果為:

[,  , --, --, *, ##, 52, 56, aaaa, acc, bbbb, 啊, 好好, 可以, 最好, 嗯嗯]

總體上看,好像是達到了目的,細分析,發現了其中“嗯嗯”竟然排在了“最好“的後臺,這就不符合按照漢字首字母進行排序的規則了,所以”嗯“的排序出現了異常。且不知道還有多少未知的漢字也會出現這樣的排序異常,所以可以初步斷定,

Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA);

比較器,並不能很好的讓漢字按照首字母拼音進行排序,但是對特殊字元、數字、英文進行排序初步斷定是沒問題的。

2,解決方案:

經過1中問題的分析,可以考慮將列表分成兩個部分:非漢字部分和漢字部分,然後分別進行排序,最後將兩部分合並。

非漢字部分排序可以使用上面的方法。下面重點就是解決漢字部分的排序,可以先將漢字轉為拼音,然後再進行比較排序。

但是注意:不能和非漢字部分和漢字部分一起都轉成拼音排序:1是先不說殊死字元無法轉換成拼音的問題;2其次也因為將漢字轉成拼音後,和原來本身就是英文的部分混合一起進行比較,就無法保證英文部分能夠排在漢字的前面了。

3,程式碼示例:

執行下面程式碼,最後輸出結果為:

[,  , --, --, *, ##, 52, 56, aaaa, acc, bbbb, 啊, 好好, 可以, 嗯嗯, 最好]
import com.google.common.collect.Lists;
import com.netease.ai.ar.dongjian.util.Pinyin4jUtil;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.text.Collator;
import java.util.Comparator;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Weichang Zhong
 * @Date: 2018/10/18
 * @Time: 16:22
 * @Description:
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class testBug {

    @Test
    public void sortList(){
        List<String> list = Lists.newArrayList();
        list.add("好好");
        list.add("最好");
        list.add("啊");
        list.add("##");
        list.add("嗯嗯");
        list.add("--");
        list.add("*");
        list.add("--");
        list.add("可以");
        list.add("56");
        list.add("");
        list.add(" ");
        list.add("bbbb");
        list.add("acc");
        list.add("52");
        list.add("aaaa");

        // 將list集合分成只包含以漢字開頭元素的集合和不包含以漢字開頭元素的集合
        List<String> chineseCharacters = Lists.newArrayList();
        List<String> notChineseCharacters = Lists.newArrayList();
        for(String str: list) {
            if(StringUtils.isNotEmpty(str) && String.valueOf(str.charAt(0)).matches("[\u4e00-\u9fa5]")) {
                // 如果開頭為漢字,則加入漢字列表中
                chineseCharacters.add(str);
            }else {
                notChineseCharacters.add(str);
            }
        }

        Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA);
        // 先對非漢字開頭內容進行排序
        notChineseCharacters.sort((o1, o2) -> ((Collator) com).compare(o1, o2));
        // 以漢字開頭的,先將漢字轉成拼音,然後進行排序
        Pinyin4jUtil pinyin4jUtil = new Pinyin4jUtil();
        chineseCharacters.sort((o1, o2) -> ((Collator) com).compare(pinyin4jUtil.getStringPinYin(o1), pinyin4jUtil.getStringPinYin(o2)));
        notChineseCharacters.addAll(chineseCharacters);
        System.out.println(notChineseCharacters.toString());
    }
}

其中Pinyin4jUtil.java

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Weichang Zhong
 * @Date: 2018/12/7
 * @Time: 9:25
 * @Description:
 */
public class Pinyin4jUtil {


    /** pinyin4j格式類 **/
    private HanyuPinyinOutputFormat format = null;
    /** 拼音字串陣列 **/
    private String[]pinyin;

    /** 通過構造方法進行初始化 **/
    public Pinyin4jUtil(){

        format = new HanyuPinyinOutputFormat();
        /*
         * 設定需要轉換的拼音格式
         * 以天為例
         * HanyuPinyinToneType.WITHOUT_TONE 轉換為tian
         * HanyuPinyinToneType.WITH_TONE_MARK 轉換為tian1
         * HanyuPinyinVCharType.WITH_U_UNICODE 轉換為tiān
         *
         */
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        pinyin = null;
    }

    /**
     * 對單個字進行轉換
     * @param pinYinStr 需轉換的漢字字串
     * @return 拼音字串陣列
     */
    public String getCharPinYin(char pinYinStr){

        try
        {
            //執行轉換
            pinyin = PinyinHelper.toHanyuPinyinStringArray(pinYinStr, format);

        } catch (BadHanyuPinyinOutputFormatCombination e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //pinyin4j規則,當轉換的符串不是漢字,就返回null
        if(pinyin == null){
            return null;
        }

        //多音字會返回一個多音字拼音的陣列,pinyiin4j並不能有效判斷該字的讀音
        return pinyin[0];
    }

    /**
     * 對單個字進行轉換
     * @param pinYinStr
     * @return
     */
    public String getStringPinYin(String pinYinStr) {
        StringBuffer sb = new StringBuffer();
        String tempStr = null;
        //迴圈字串
        for (int i = 0; i < pinYinStr.length(); i++) {

            tempStr = this.getCharPinYin(pinYinStr.charAt(i));
            if (tempStr == null) {
                //非漢字直接拼接
                sb.append(pinYinStr.charAt(i));
            } else {
                sb.append(tempStr);
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        Pinyin4jUtil pinyin4jUtil = new Pinyin4jUtil();
        String str = "你在做什麼?what are you nong sa lie?";
        System.out.println(pinyin4jUtil.getStringPinYin(str));

        System.out.println(String.valueOf(str.charAt(0)).matches("[\u4e00-\u9fa5]"));

    }

}

pom 引入的maven jar包:

        <dependency>
            <groupId>net.sourceforge.pinyin4j</groupId>
            <artifactId>pinyin4j</artifactId>
            <version>2.5.0</version>
        </dependency>