1. 程式人生 > >Java自定義比較器實現中文排序

Java自定義比較器實現中文排序

compareTo 方法

  compareTo()是兩個字串物件比較大小,返回一個整數值,如果呼叫字串物件大,返回正整數,反之,返回負整數。相等則返回0。compareTo()是兩個字串物件按ASCII比較大小(漢字是Unicode),返回一個整數值,如果呼叫字串物件大,返回正整數,反之,返回負整數。相等則返回0。

Comparator 比較器

  Java 內實現自定義比較器比較簡單,實現Comparator介面的compare()這個方法來制定排序規則,按照Java規範應滿足以下約定,否則會拋Comparison method violates its general contract 異常。規則如下:

同時應滿足以下約定:
+ 自反性 sgn(compare(x, y)) == -sgn(compare(y, x))
+ 傳遞性 compare(x, y) > 0 compare(y, z)>0) =>得出 compare(x, z)>0
+ 一致性 (compare(x, y)==0) == (x.equals(y)),這點規範中原文是“not strictly required”,不是必須的,但是實現者應該知道不一致的後果,所以儘量實現這一要求.

    Comparator<String> comparator = new Comparator<String>() {
        @Override
public int compare(String s1, String s2) { return s1.compareTo(s2); } };

以下程式碼示例:

    @Test
    public void testCompare() {
        List<String> list = new ArrayList<>();
        list.add("java");
        list.add("php");
        list.add("c++");
        System.out.println("排序前-->"
+ list); Comparator<String> comparator = new Comparator<String>() { @Override public int compare(String s1, String s2) { return s1.compareTo(s2); } }; Collections.sort(list, comparator); System.out.println("排序後-->" + list); Collections.reverse(list); System.out.println("排序後逆序-->" + list); }

輸出結果為:

Comparator中文排序

  中文漢字是Unicode編碼,所以排序時不是我們習慣用的拼音字母。如果還是剛才的實現,程式碼如下:

    @Test
    public void testCompareCN() {
        List<String> list = new ArrayList<>();
        list.add("中國");// 中->20013 unicode編碼的4E2D
        list.add("英國");// 英-->33521 unicode編碼的82F1
        list.add("美國");// 美->32654 unicode編碼的7F8E
        // 漢字unicode編碼表 http://www.chi2ko.com/tool/CJK.htm
        System.out.println("排序前-->" + list);

        Comparator<String> comparator = new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                int b = s1.compareTo(s2);
                return b;
            }
        };

        Collections.sort(list, comparator);

        System.out.println("排序後-->" + list);
        Collections.reverse(list);
        System.out.println("排序後逆序-->" + list);

        // 輸出字元編碼對應的十進位制
        //char a = '美';
        //System.out.println((int) a);
    }

輸出結果為:

  這個結果不符合我們的排序習慣,因此應該用Collator指定Locale.CHINA,程式碼應如下:

    @Test
    public void testCollator() {
        List<String> list = new ArrayList<>();
        list.add("中國");
        list.add("英國");
        list.add("美國");
        System.out.println("排序前-->" + list);
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                String o1 = "";
                String o2 = "";
                if (s1 != null) {
                    o1 = s1;
                }
                if (s2 != null) {
                    o2 = s2;
                }
                Collator instance = Collator.getInstance(Locale.CHINA);
                return instance.compare(o1, o2);
            }
        });

        System.out.println("排序後-->" + list);
        Collections.reverse(list);
        System.out.println("排序後逆序-->" + list);

    }

輸出結果為:

需要注意的是,compareTo不能傳入null,自定義比較器時要注意。

部落格原文