在以前的一次Java上機實習中,老師佈置了一道很簡單的題:java
從控制檯輸入10個整數,對它們進行升序排序並輸出。算法
考慮到只有10個數,須要比較的次數不是不少,因此當時我本身寫了一段冒泡排序的算法而後就上交做業。交做業以後我忽然想到一個問題:JDK是否有相似於STL中的std::sort方法,能實現基本的排序而無需用戶本身實現?dom
第9版《Java核心技術卷Ⅰ》的第607頁介紹了一個方法:ide
Collections類中的sort方法能夠對實現了List接口的集合進行排序。這個方法假定列表元素實現了Comparable接口。函數
查看Java官方文檔可知,sort方法有兩種重載形式。第一種重載是:this
static <T extends Comparable<? super T>> void sort(List<T> list)
根據官方文檔的描述,這個方法將列表元素進行升序排序,可是列表要知足如下條件:
1.列表元素實現了Comparable接口,且任意兩個列表元素都是可比的。
2.列表必須支持set方法。
若是要經過這個方法來完成我上面提到的做業,那顯然是行得通的:整數能夠進行相互比較,第一個條件知足;把10個整數放入一個ArrayList或LinkedList中,這兩個列表都支持set方法,第二個條件知足。實現代碼以下:spa
import java.util.*; public class Sort { public static void main(String[] args) { Scanner scan = new Scanner(System.in); List<Integer> list = new ArrayList<>(); //用戶輸入10個整數 System.out.println("請輸入10個整數:"); for(int i = 0; i < 10; i++) { list.add(scan.nextInt()); } scan.close(); //排序 Collections.sort(list); //輸出排序結果 System.out.println(list); } }
程序運行結果以下:code
用sort方法能夠很方便地實現升序排序,但可否進行降序排序?答案是確定的,《Java核心技術卷Ⅰ》中介紹了一種用sort進行降序排序的簡潔方法。這種方法須要用到sort方法的第二種重載形式:orm
public static <T> void sort(List<T> list,Comparator<? super T> c)
若是想採用其餘方式進行排序,那麼可將一個Comparator對象做爲sort方法的第二個參數。當要進行逆序排序時,最簡便的方法是將Collections.reverseOrder()做爲第二個參數。對象
import java.util.*; public class Sort { public static void main(String[] args) { Scanner scan = new Scanner(System.in); List<Integer> list = new ArrayList<>(); //用戶輸入10個整數 System.out.println("請輸入10個整數:"); for(int i = 0; i < 10; i++) { list.add(scan.nextInt()); } scan.close(); //逆序排序 Collections.sort(list,Collections.reverseOrder()); //輸出排序結果 System.out.println(list); } }
程序運行結果以下:
在上面的例子中,列表中的元素是整數,因此排序邏輯是很顯然的:若是是升序排序,那就小數在前,大數在後。可是,若是排序的對象並不是屬於整數、浮點數之類的基本數據類型,那麼這些對象之間的「大小」關係該如何定義?假設有這樣一道題:
定義一個點類,其中有整型屬性x和y,表明其座標;除了這兩個屬性之外沒有其餘屬性。隨機產生10個點,並按照這些點與原點(0,0)之間的距離大小對點進行降序排序。
若是仍想經過sort方法進行排序的話,首先點類就必須知足上面曾經提過的約束條件:點對象是可比的,所以點類必須實現Comparable接口。查看官方文檔可知,Comparable接口中只有一個方法:
int compareTo(T o)
調用這個方法的對象將會與參數o進行比較,小於o、等於o和大於o分別對應的返回值爲負數、0和正數。對象之間相對大小的判斷方法是自定義的,在這個問題中,就是經過比較各點與原點之間的距離來判斷大小,因此點類的實現以下:
class Point implements Comparable<Point>{ private int x; private int y; public Point(int x,int y) { this.x = x; this.y = y; } @Override //若是該點到原點的距離大於o點到原點的距離,則該點大於o點 public int compareTo(Point o) { int distance1 = (this.x) * (this.x) + (this.y) * (this.y); int distance2 = (o.x) * (o.x) + (o.y) * (o.y); return (distance1 > distance2) ? 1 : ((distance1 == distance2) ? 0 : -1); } @Override public String toString() { return "(" + x + ","+ y + ")"; } }
由於要進行降序排序,因此能夠經過將Collections.reverseOrder()做爲sort方法的第二個參數來實現:
public class SortDemo { private static List<Point> list = new ArrayList<>(); public static void main(String[] args) { //隨機生成10個點 for(int i = 0; i < 10; i++) { //點的座標取值在[1,20]之間 int x = (int)(Math.random() * 20) + 1; int y = (int)(Math.random() * 20) + 1; list.add(new Point(x,y)); } System.out.print("排序前:"); System.out.println(list); //降序排序 Collections.sort(list,Collections.reverseOrder()); System.out.print("排序後:"); System.out.println(list); } }
程序結果以下:
如今對sort方法進行小結:
實現了Comparable接口的類均可以用sort方法進行排序,默認的排序方法是升序;若是想進行降序排序,只需把Collections.reverseOrder做爲第二個參數傳給sort方法。
上面反覆提到的Collections.reverseOrder方法返回的是一個Comparator對象。其實Comparator接口並不陌生,經常使用的equals方法就來自這個接口。Comparator接口用來定義兩個對象之間的比較方法,它有一個叫作compare的方法,函數簽名以下:
int compare(T o1,T o2)
o1 > o2,返回正數;o1 = o2,返回0;o1 < o2,返回負數。
從前面的例子能夠看出,可使用Comparator對象來控制sort的排序方法,這是如何實現的?查看sort方法的相關源碼,我發現其中有這樣一段代碼:
經過Comparator對象來實現點對象的降序排序,一種可行的實現方式以下:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; //點類 class Point { private int x; private int y; public Point(int x,int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } @Override public String toString() { return "(" + x + ","+ y + ")"; } } public class SortDemo { private static List<Point> list = new ArrayList<>(); public static void main(String[] args) { //隨機生成10個點 for(int i = 0; i < 10; i++) { //點的座標取值在[1,20]之間 int x = (int)(Math.random() * 20) + 1; int y = (int)(Math.random() * 20) + 1; list.add(new Point(x,y)); } System.out.print("排序前:"); System.out.println(list); //降序排序 Collections.sort(list,new Comparator<Point>() { @Override //當 o1 < o2 時返回正數 public int compare(Point o1, Point o2) { int distance1 = (o1.getX()) * (o1.getX()) + (o1.getY()) * (o1.getY()); int distance2 = (o2.getX()) * (o2.getX()) + (o2.getY()) * (o2.getY()); return (distance1 < distance2) ? 1 : ((distance1 == distance2) ? 0 : -1); } }); System.out.print("排序後:"); System.out.println(list); } }
程序運行結果以下:
注意,在上面的程序中Point類並無實現Comparable接口,這是由於已經經過實現Comparator接口來定義Point對象的比較方法,因此也就無需實現Comparable接口。