前提
在處理與線性數據結構有關的問題的時候,經常需要用到排序。我們知道,對於基礎類型的數組,我們可以用Arrays.sort()
這個函數來進行排序,方便又快捷。但是對於泛型列表類型List
,我們就束手無策了。 這篇博文主要總結對各類線性數據結構的排序方法。
對基礎類型和封裝類型的數組進行排序
所謂基礎類型,即int
、double
、boolean
、char
等;所謂封裝類型,即Integer
、Double
、String
、Boolean
等。當我們需要對它們構成的數組進行排序時,可以調用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()
函數都有默認的排序規則,總體上依照數值上小的在前面,大的在後面這樣的規則。
int
、float
、double
、Integer
、String
、Boolean
這類的就不用多說了,按數值大小排;
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;
}
}
這裏用了兩個嵌套三元運算符?:
來比較用戶a
和b
的年齡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);
}
可以看到,它調用了List
的sort
函數,再點進去:
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);
}
}
可以看這個函數的前兩行,它實際就是把list
用toArray
函數轉換成數組,然後調用的是Arrays.sort()
需要傳入比較器的那個重載。