1. 程式人生 > >guava之Ordering的使用例項

guava之Ordering的使用例項

guava的ordering這個類的使用,幫助程式碼排序。很不錯的。

1,先是簡單的排序使用。

    /**
     * 預設的排序器
     * natural() 對可排序型別做自然排序,如數字按大小,日期按先後排序
     * reverse() 對當前的比較器進行反轉
     * 自然排序,不能將漢字按首字母的順序排序。
     */
    private static void naturalTest() {
        List<String> list = Lists.newArrayList("12", "2", "3", "33", "4", "44", "5", "55", "測試", "基線", "有錢");

        Ordering<Comparable> natural = Ordering.natural();
        list.sort(natural);
        System.out.println(list.toString());
        //反轉
        list.sort(natural.reverse());
        System.out.println(list.toString());

        List<Integer> ints = Lists.newArrayList(12, 2, 3, 33, 4, 44, 5, 55);
        ints.sort(natural);
        System.out.println(ints.toString());
        ints.sort(natural.reverse());
        System.out.println(ints.toString());
    }

執行結果:

大師兄

對所傳list進行系統預設的排序,一般情況下,沒問題,但是如果要漢字內容按字母表順序排的話就不行啦,

上面程式碼裡面順便示範了下“反轉”,就是把排序器給反轉一下的功能。對應的方法reverse();

2,常用的簡單示範

    /**
     * 實現自定義的排序器
     * 常用姿勢,傳入需要比較的物件,然後使用對應的屬性去compare,返回int。返回個比較器,然後list就可以使用啦。
     * 這地方使用的是簡單的字串,還示範了使用傳入自定義類物件,根據某個屬性排序的例子。
     */
    private static void usually() {
        List<String> list = Lists.newArrayList("12345", "2345", "345", "34", "4", "", "5", "55", "測試", "基線", "有錢");
        Ordering<String> lengthOrdering = new Ordering<String>() {
            @Override
            public int compare(String left, String right) {
                return Ints.compare(left.length(), right.length());
            }
        };
        list.sort(lengthOrdering);
        System.out.println(list.toString());

        list.sort(lengthOrdering.reverse());
        System.out.println(list.toString());


        //這樣漢字就可以按首字母排序啦。
        Ordering<String> stringOrdering = new Ordering<String>() {
            @Override
            public int compare(String left, String right) {
                return Collator.getInstance(Locale.CHINA).compare(left, right);
            }
        };
        list.sort(stringOrdering);
        System.out.println(list.toString());
    }

執行結果:

大師兄

這個地方就對漢字的排序做了下操作,然後就可以按首字母排序啦。這地方使用的是簡單的字串來排序的。

3,對自定義的類,安照某個屬性去排序的示範。

    /**
     * 對某個類的某個屬性進行排序,很常用的姿勢。
     */
    private static void classCompare() {
        //集合初始化的時候,若大小可知,應初始化固定大小的集合,也是個好習慣。
        List<Person> persons = Lists.newArrayListWithExpectedSize(4);
        persons.add(new Person(11, "周星馳"));
        persons.add(new Person(99, "陳世美"));
        persons.add(new Person(21, "潘金蓮"));
        persons.add(new Person(15, "阿姆斯特丹"));

        persons.forEach(person -> System.out.print(person.getAge() + " "));
        System.out.println();
        persons.sort(OrderingConstants.AGE_ORDERING);
        persons.forEach(person -> System.out.print(person.getAge() + " "));
        System.out.println();

        persons.forEach(person -> System.out.print(person.getName() + " "));
        System.out.println();
        persons.sort(OrderingConstants.NAME_ORDERING);
        persons.forEach(person -> System.out.print(person.getName() + " "));
        System.out.println();
    }

執行結果:

大師兄

一個是按照年紀排序,一個是按照名字排序。額,這個person類,我就不展示啦,就一個名字String和年齡int兩個屬性。

還有,兩個排序器,因為通用,我就給提出來了,放到一個單獨的地方,可以通用。


    /**
     * 排序器的儲存地方
     */
    interface OrderingConstants {

        /**
         * 按 age 排序,一定要判斷一下對比的物件以及欄位為null的情況,不然會bug的,雖然你當時可能不會報錯。
         */
        Ordering<Person> AGE_ORDERING = new Ordering<Person>() {
            @Override
            public int compare(Person left, Person right) {
                if (left == null && right == null) {
                    return 0;
                }
                if (left == null) {
                    return 1;
                }
                if (right == null) {
                    return -1;
                }
                //這個地方不要自己去 a - b ,不要自己去算,因為int型別可以自己減少,但是long型可能就炸啦
                //這地方除了Ints,還有Longs,可以看下原始碼的這個資料夾下的相同效果的類。
                return Ints.compare(left.getAge(), right.getAge());
            }
        };

        /**
         * 按 name 排序,一定要判斷一下對比的物件以及欄位為null的情況,不然會bug的,雖然你當時可能不會報錯。
         */
        Ordering<Person> NAME_ORDERING = new Ordering<Person>() {
            @Override
            public int compare(Person left, Person right) {
                if (left == null && right == null) {
                    return 0;
                }
                if (left == null) {
                    return 1;
                }
                if (right == null) {
                    return -1;
                }
                if (left.getName() == null && right.getName() == null) {
                    return 0;
                }
                if (left.getName() == null) {
                    return 1;
                }
                if (right.getName() == null) {
                    return -1;
                }
                return Collator.getInstance(Locale.CHINA).compare(left.getName(), right.getName());
            }
        };
    }

在實際專案裡面,也可以這麼幹,把所有排序相關的排序器都放在一個地方,方便通用。

4,獲得給定集合的有序副本。

    /**
     * 返回指定的元素的排序副本,不修改原來的list。
     */
    private static void sortedCopy() {
        List<String> list = Lists.newArrayList("12345", "2345", "345", "34", "4", "", "5", "55", "測試", "基線", "有錢");
        List<String> sortedCopy = Ordering.natural().sortedCopy(list);
        System.out.println(list.toString());
        System.out.println(sortedCopy.toString());
    }

大師兄

這個執行結果,可以看出來,原來的集合是啥還是啥,然後獲得了個有序的集合。

5,把原來的順序打亂,返回。

    /**
     * 把原來的順序,任意打亂,返回。測試幾次,返回的都一樣,不是隨機的。
     * 好像沒啥用的樣子
     */
    private static void arbitrary() {
        List<String> list = Lists.newArrayList("1", "2", "3", "4", "5", "4", "3", "2", "1", "0");
        Ordering<Object> arbitrary = Ordering.arbitrary();
        System.out.println(list.toString());
        list.sort(arbitrary);
        System.out.println(list.toString());
    }

大師兄

這個返回結果不是說每次都不一樣,結果是固定都。

6,先是按照屬性1排序,要是相同了,再繼續按屬性2排序。

    /**
     * 先是按年紀排序,年紀相同,再按名稱排序。
     */
    private static void sortTwoWay() {
        //集合初始化的時候,若大小可知,應初始化固定大小的集合,也是個好習慣。
        List<Person> persons = Lists.newArrayListWithExpectedSize(6);
        persons.add(new Person(11, "周星馳"));
        persons.add(new Person(11, "吳孟達"));
        persons.add(new Person(44, "陳世美"));
        persons.add(new Person(44, "小金金--是程咬金的意思,不是潘金蓮。。。"));
        persons.add(new Person(22, "潘金蓮"));
        persons.add(new Person(22, "武松"));
        persons.add(new Person(33, "阿姆斯特丹"));
        persons.add(new Person(33, "阿姆斯特朗"));

        //可以拿出去,分開宣告,然後如下合併一起。程式碼好看些。
        Ordering<Person> ordering = OrderingConstants.AGE_ORDERING.compound(OrderingConstants.NAME_ORDERING);
        persons.sort(ordering);
        persons.forEach(person -> System.out.println(person.toString()));
    }

大師兄

可以看到結果是,先按照年紀排序,年紀相同了,就按照名稱排序,名稱排序是按照字母表順序排的。