Java排序方法總結


前提

在處理與線性數據結構有關的問題的時候,經常需要用到排序。我們知道,對於基礎類型的數組,我們可以用Arrays.sort()這個函數來進行排序,方便又快捷。但是對於泛型列表類型List,我們就束手無策了。 這篇博文主要總結對各類線性數據結構的排序方法。


對基礎類型和封裝類型的數組進行排序

所謂基礎類型,即intdoublebooleanchar等;所謂封裝類型,即IntegerDoubleStringBoolean等。當我們需要對它們構成的數組進行排序時,可以調用Arrays.sort()函數來做,它內部使用歸併排序,時間消耗上比快速排序要穩定。

舉一個例子:

	int[] array = new int[]{1, 9, 3, 7, 4, 6, 8, 2, 5};
    Arrays.sort(array);

排序結果:

1 2 3 4 5 6 7 8 9

默認排序規則

針對每種數據類型,Arrays.sort()函數都有默認的排序規則,總體上依照數值上小的在前面,大的在後面這樣的規則。
intfloatdoubleIntegerStringBoolean這類的就不用多說了,按數值大小排;
char按照字符ASCII碼的大小來排;
String從每個字符串的第一個字符開始比較ASCII碼,小的在前,大的在後;
Boolean按照false < true的規則進行排序
......


對泛型列表List<T>進行排序

泛型列表List<T>是除數組外,我們最經常用到的線性數據結構。與數組相比,它的優點在於可變長。 比如我們可以定義以下的List:

	List<Integer> nums = new ArrayList<>();
	class User {
		int id;
		int age;
		String name;
	}
	List<User> users = new ArrayList<>();

對List進行排序,我們可以調用Collections.sort()函數,他有兩個重載:

	sort(List<T> list)
	sort(List<T> list, Comparator<? super T> c)

對於上述nums這種只存單值的列表來說,用第一個重載就可以,默認的排序規則就可以滿足要求。
對於上述users這種存放自定義類型的列表來說,我們所需的排序規則可能會根據需求發生變化,比如,我需要根據年齡age排序,或者我需要根據姓名name排序,那麼此時就需要上述的第二種重載,由此我們就需要引入比較器Comparator


比較器Comparator

Comparator是一個類,需要自定義一個Comparator時需要繼承它然後實現compare方法。
該方法的返回值爲int型,它關注的是兩個被比較的對象何時算作前者大於後者(返回1)、何時算作相等(返回0)、以及何時算作後者大於前者(返回-1)。
舉例說明:

    private class UserAgeComparator implements Comparator<User> {
        @Override
        public int compare(User a, User b) {
            return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
        }
    }

這裏用了兩個嵌套三元運算符?:來比較用戶ab的年齡age,當a.age > b.age時返回1,當a.age < b.age時返回-1,否則返回0


執行排序

執行排序的時候,只需要調用Collections.sort()函數,傳入待排序的列表和自定義的比較器的實例

	Collections.sort(user, new UserAgeComparator());

親測速度很快,再也不用背快排算法了,哈哈。


後記

其實深究起Collections.sort()的實現:

    public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);
    }

可以看到,它調用了Listsort函數,再點進去:

    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }

可以看這個函數的前兩行,它實際就是把listtoArray函數轉換成數組,然後調用的是Arrays.sort()需要傳入比較器的那個重載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章