Java中Collections.sort的使用
第9版《Java核心技術(shù)卷Ⅰ》的第607頁介紹了一個(gè)方法:
Collections類中的sort方法可以對實(shí)現(xiàn)了List接口的集合進(jìn)行排序。這個(gè)方法假定列表元素實(shí)現(xiàn)了Comparable接口。
查看Java官方文檔可知,sort方法有兩種重載形式。第一種重載是:
static <T extends Comparable<? super T>> void sort(List<T> list)
根據(jù)官方文檔的描述,這個(gè)方法將列表元素進(jìn)行升序排序,但是列表要滿足以下條件:
1.列表元素實(shí)現(xiàn)了Comparable接口,且任意兩個(gè)列表元素都是可比的。
2.列表必須支持set方法。
如果要通過這個(gè)方法來完成我上面提到的作業(yè),那顯然是行得通的:整數(shù)可以進(jìn)行相互比較,第一個(gè)條件滿足;把10個(gè)整數(shù)放入一個(gè)ArrayList或LinkedList中,這兩個(gè)列表都支持set方法,第二個(gè)條件滿足。實(shí)現(xiàn)代碼如下:
import java.util.*; public class Sort { public static void main(String[] args) { Scanner scan = new Scanner(System.in); List<Integer> list = new ArrayList<>(); //用戶輸入10個(gè)整數(shù) System.out.println("請輸入10個(gè)整數(shù):"); for(int i = 0; i < 10; i++) { list.add(scan.nextInt()); } scan.close(); //排序 Collections.sort(list); //輸出排序結(jié)果 System.out.println(list); } }
程序運(yùn)行結(jié)果如下:
用sort進(jìn)行升序排序
用sort方法可以很方便地實(shí)現(xiàn)升序排序,但能否進(jìn)行降序排序?答案是肯定的,《Java核心技術(shù)卷Ⅰ》中介紹了一種用sort進(jìn)行降序排序的簡潔方法。這種方法需要用到sort方法的第二種重載形式:
public static <T> void sort(List<T> list,Comparator<? super T> c)
如果想采用其他方式進(jìn)行排序,那么可將一個(gè)Comparator對象作為sort方法的第二個(gè)參數(shù)。當(dāng)要進(jìn)行逆序排序時(shí),最簡便的方法是將Collections.reverseOrder()作為第二個(gè)參數(shù)。
import java.util.*; public class Sort { public static void main(String[] args) { Scanner scan = new Scanner(System.in); List<Integer> list = new ArrayList<>(); //用戶輸入10個(gè)整數(shù) System.out.println("請輸入10個(gè)整數(shù):"); for(int i = 0; i < 10; i++) { list.add(scan.nextInt()); } scan.close(); //逆序排序 Collections.sort(list,Collections.reverseOrder()); //輸出排序結(jié)果 System.out.println(list); } }
程序運(yùn)行結(jié)果如下:
用sort進(jìn)行降序排序
更進(jìn)一步:排序?qū)ο蟛皇腔緮?shù)據(jù)類型
在上面的例子中,列表中的元素是整數(shù),所以排序邏輯是很顯然的:如果是升序排序,那就小數(shù)在前,大數(shù)在后。但是,如果排序的對象并非屬于整數(shù)、浮點(diǎn)數(shù)之類的基本數(shù)據(jù)類型,那么這些對象之間的“大小”關(guān)系該如何定義?假設(shè)有這樣一道題:
定義一個(gè)點(diǎn)類,其中有整型屬性x和y,代表其坐標(biāo);除了這兩個(gè)屬性以外沒有其他屬性。隨機(jī)產(chǎn)生10個(gè)點(diǎn),并按照這些點(diǎn)與原點(diǎn)(0,0)之間的距離大小對點(diǎn)進(jìn)行降序排序。
如果仍想通過sort方法進(jìn)行排序的話,首先點(diǎn)類就必須滿足上面曾經(jīng)提過的約束條件:點(diǎn)對象是可比的,因此點(diǎn)類必須實(shí)現(xiàn)Comparable接口。查看官方文檔可知,Comparable接口中只有一個(gè)方法:
int compareTo(T o)
調(diào)用這個(gè)方法的對象將會與參數(shù)o進(jìn)行比較,小于o、等于o和大于o分別對應(yīng)的返回值為負(fù)數(shù)、0和正數(shù)。對象之間相對大小的判斷方法是自定義的,在這個(gè)問題中,就是通過比較各點(diǎn)與原點(diǎn)之間的距離來判斷大小,所以點(diǎn)類的實(shí)現(xiàn)如下:
class Point implements Comparable<Point>{ private int x; private int y; public Point(int x,int y) { this.x = x; this.y = y; } @Override //如果該點(diǎn)到原點(diǎn)的距離大于o點(diǎn)到原點(diǎn)的距離,則該點(diǎn)大于o點(diǎn) 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 + ")"; } }
因?yàn)橐M(jìn)行降序排序,所以可以通過將Collections.reverseOrder()作為sort方法的第二個(gè)參數(shù)來實(shí)現(xiàn):
public class SortDemo { private static List<Point> list = new ArrayList<>(); public static void main(String[] args) { //隨機(jī)生成10個(gè)點(diǎn) for(int i = 0; i < 10; i++) { //點(diǎn)的坐標(biāo)取值在[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); } }
程序結(jié)果如下:
對點(diǎn)進(jìn)行降序排序
現(xiàn)在對sort方法進(jìn)行小結(jié):
實(shí)現(xiàn)了Comparable接口的類都可以用sort方法進(jìn)行排序,默認(rèn)的排序方法是升序;如果想進(jìn)行降序排序,只需把Collections.reverseOrder作為第二個(gè)參數(shù)傳給sort方法。
了解Comparator接口
上面反復(fù)提到的Collections.reverseOrder方法返回的是一個(gè)Comparator對象。其實(shí)Comparator接口并不陌生,常用的equals方法就來自這個(gè)接口。Comparator接口用來定義兩個(gè)對象之間的比較方法,它有一個(gè)叫做compare的方法,函數(shù)簽名如下:
int compare(T o1,T o2)
o1 > o2,返回正數(shù);o1 = o2,返回0;o1 < o2,返回負(fù)數(shù)。
從前面的例子可以看出,可以使用Comparator對象來控制sort的排序方法,這是如何實(shí)現(xiàn)的?查看sort方法的相關(guān)源碼,我發(fā)現(xiàn)其中有這樣一段代碼:
sort方法的相關(guān)源碼
注意看圖中用紅線框起來的部分。經(jīng)分析可知,這段代碼實(shí)現(xiàn)了這樣的邏輯:如果compare的返回值為正數(shù),就交換進(jìn)行比較的兩個(gè)元素的位置。于是可以得出這樣一個(gè)結(jié)論,如果讓 x > y 時(shí)compare(x,y)返回正數(shù),那么交換 x 和 y 的位置后大的元素在后,這就實(shí)現(xiàn)了升序排序;反之,如果讓 x < y 時(shí)compare(x,y)返回正數(shù),那么交換位置后小的元素在后,這就實(shí)現(xiàn)了降序排序。這就是Comparator對象控制排序方式的原理。
Comparator對象控制排序方式的原理
通過Comparator對象來實(shí)現(xiàn)點(diǎn)對象的降序排序,一種可行的實(shí)現(xiàn)方式如下:
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; //點(diǎn)類 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) { //隨機(jī)生成10個(gè)點(diǎn) for(int i = 0; i < 10; i++) { //點(diǎn)的坐標(biāo)取值在[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 //當(dāng) o1 < o2 時(shí)返回正數(shù) 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); } }
程序運(yùn)行結(jié)果如下:
通過實(shí)現(xiàn)Comparator接口來進(jìn)行降序排序
注意,在上面的程序中Point類并沒有實(shí)現(xiàn)Comparable接口,這是因?yàn)橐呀?jīng)通過實(shí)現(xiàn)Comparator接口來定義Point對象的比較方法,所以也就無需實(shí)現(xiàn)Comparable接口。
Collections.sort(list,new Comparator<Point>() { @Override public int compare(Point o1, Point o2) { //常見寫法 return o1.x-o2.x; //由上面分析,源碼,可知,return=1的時(shí)候,會交換o1和o2,o1排到o2后面,因此大的對象o1排在小的后面,就是升序 return o2.x-o1.x; //反之就是降序 }
到此這篇關(guān)于Java中Collections.sort的使用的文章就介紹到這了,更多相關(guān)Java Collections.sort內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java中Collections.sort排序函數(shù)用法詳解
- JAVA對list集合進(jìn)行排序Collections.sort()
- Java?Collections.sort()實(shí)現(xiàn)List排序的默認(rèn)方法和自定義方法
- java中Collections.sort排序詳解
- Java Collections.sort()排序代碼案例
- 詳解java Collections.sort的兩種用法
- Java使用Collections.sort()排序的示例詳解
- Java使用Collections.sort()排序的方法
- JAVA中Collections.sort()方法使用詳解
相關(guān)文章
Java利用EasyExcel解析動(dòng)態(tài)表頭及導(dǎo)出實(shí)現(xiàn)過程
以前做導(dǎo)出功能,表頭和數(shù)據(jù)都是固定的,下面這篇文章主要給大家介紹了關(guān)于Java利用EasyExcel解析動(dòng)態(tài)表頭及導(dǎo)出實(shí)現(xiàn)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12使用jmeter實(shí)現(xiàn)對jar包的調(diào)用方式
這篇文章主要介紹了使用jmeter實(shí)現(xiàn)對jar包的調(diào)用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03在2023idea中實(shí)現(xiàn)SpringBoot的IoC和AOP的方法
這篇文檔詳細(xì)介紹了如何在Spring Boot中實(shí)現(xiàn)IoC(控制反轉(zhuǎn))和AOP(面向切面編程),深入探討了AOP的基本概念,包括AOP的作用、優(yōu)勢以及實(shí)現(xiàn)方式,最后,它提到了AOP的注解,如@Aspect、@Pointcut、@Before、@After、@AfterReturning、@AfterThrowing和@Around2024-11-11SpringBoot項(xiàng)目更換項(xiàng)目名稱的實(shí)現(xiàn)
本文主要介紹了SpringBoot項(xiàng)目更換項(xiàng)目名稱,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06java類Circle定義計(jì)算圓的面積和周長代碼示例
要用Java計(jì)算圓的周長和面積,需要使用圓的半徑和一些數(shù)學(xué)公式,下面這篇文章主要給大家介紹了關(guān)于java類Circle定義計(jì)算圓的面積、周長的相關(guān)資料,需要的朋友可以參考下2024-04-04Springboot通過url訪問本地圖片代碼實(shí)例
這篇文章主要介紹了springboot通過url訪問本地圖片代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03SpringBoot項(xiàng)目啟動(dòng)后立馬自動(dòng)關(guān)閉的解決方案
這篇文章主要介紹了SpringBoot項(xiàng)目啟動(dòng)后立馬自動(dòng)關(guān)閉的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03