排序是編程中常常須要用到的功能,而 Java 的工具類 Collections 中也提供了 sort 方法用於實現對列表等集合中元素的排序。Collections.sort() 方法有兩種形式:Collections.sort(List)
和 Collections.sort(List, Comparator)
。java
第一種 Collections.sort(List)
要求 List 中的元素已經實現了 Comparable 接口,第二種 Collections.sort(List, Comparator)
則須要實現一個比較器。基於比較的排序的關鍵就是能比較兩個元素的大小,知道了誰大誰小,才能肯定誰排在前面誰排在後面;而這兩種方法的本質都是爲了肯定兩個元素誰大誰小。接下來主要談一談基於比較器的自定義排序。編程
先看個排序示例:工具
public static void main(String[] args) { Integer[] input = { 1, 3, 8, 7, 4, 9, 2 }; List<Integer> lst = Arrays.asList(input); Collections.sort(lst); System.out.println(lst); } //輸出爲: [1, 2, 3, 4, 7, 8, 9]
能夠看到,本來無序的列表變成了從小到大排列。緣由有二:code
然而大多數狀況下,咱們想要的都不是簡單的升序排列,這時候自定義排序就要派上用場了。Comparator 實現自定義排序的關鍵是實現 compare 方法,該方法聲明爲:排序
int compare(T o1, T o2);
當方法返回負值時,表明 o1 < o2;當方法返回 0 時,表明 o1 = o2;當方法返回正值時,表明 o1 > o2;下面以實現降序排列爲例,演示如何使用 Comparator。接口
###1、降序排列input
public class Main { public static void main(String[] args) { Integer[] input = { 1, 3, 8, 7, 4, 9, 2 }; List<Integer> lst = Arrays.asList(input); Collections.sort(lst, new IntComparator<Integer>()); System.out.println(lst); } } class IntComparator<T> implements Comparator<T> { public int compare(T a, T b) { return (Integer)b - (Integer)a; } } //輸出爲: [9, 8, 7, 4, 3, 2, 1]
爲何這樣就實現了降序排列呢?io
這是由於當傳入 Comparator 參數時, sort 方法會將須要比較大小的兩個元素 a,b 做爲參數傳給 Comparator.compare(T a, T b) 方法,根據返回的結果判斷 a,b 的大小。例如,傳入1 和 3 的時候,compare 返回 2,正值表明 a > b,即 1 「大於」 3,這個「大於」正是咱們本身定義的規則。而後,根據 sort 方法默認從小到大排序的性質,小的排在前面,因此最後 3 排在 1 前面,也就實現了降序排列。class
在這裏 return (Integer)b - (Integer)a;
是一種經驗寫法,若是分解開來應該是這樣:List
class IntComparator<T> implements Comparator<T> { public int compare(T a, T b) { int num1 = (Integer)a; int num2 = (Integer)b; if(num1 > num2) { //若是 a>b,根據自定義規則 a 應該在前面,即自定義規則中 a 「小於」 b,故此時返回負值 return -1; } else if(num1 < num2) { return 1; } else { return 0; } } }
該 compare 方法很是簡單,但在實際應用中,因爲自定義規則的複雜性,compare 的編寫難度也可能變得很大。下面再舉一例,讓你們加深對 compare 的理解。
###2、奇偶排列 要求:奇數排在偶數前面,奇數之間從小到大排列,偶數之間從大到小排序
class IntComparator<T> implements Comparator<T> { public int compare(T a, T b) { int num1 = (Integer)a; int num2 = (Integer)b; if(num1 % 2 == 1 && num2 % 2 == 1) { return num1 - num2; // ① } else if(num1 % 2 == 0 && num2 % 2 == 0) { return num2 - num1; // ② } else if(num1 % 2 == 1 && num2 % 2 == 0) { return -1; // ③ } else { return 1; // ④ } } }
① ② 表示兩數同奇或同偶的狀況,此時根據經驗寫法很容易獲得。
③ ④ 表示奇偶不一樣的狀況,此時若 a 爲奇數,b 爲偶數,則 a 應該排在 b 前面,即 a 「小於」 b,故返回負值;反之,返回正值。
最後,再次強調:排在前面的元素「小」,排在後面的元素「大」。
留個練習,有興趣的朋友能夠作下,看看本身是否是真的掌握了。
練習題:實現數字按照高位到低位的比較,進行降序排序;高位相同的,位數少的排前面。例如:輸入 {3, 34, 5, 7, 56, 523, 52, 571};輸出 {7, 5, 571, 56, 52, 523, 3, 34}