先上代碼:
packagejava.lang;publicinterfaceComparable<T>{publicintcompareTo(To);}
可以看出這個接口只有一個方法,這個方法只有一個參數,實現了這個接口的類就可以和同類進行比較了。這個方法所實現的,就是比較法則,也是說,它表示如何對兩個對象進行比較。 它返回的是一個整數int:
返回正數,代表當前對象大于被比較的對象;
返回0,代表當前對象等于于被比較的對象;
返回負數,代表當前對象小于被比較的對象。
實現了該接口后,我們就可以使用Arrays.sort()和Collections.sort()來進行排序了。 不然對象沒有比較法則,程序肯定是不知道如何進行比較排序的。 像我們常用的類String、Integer、Double、Date等,JDK都幫我們實現了Comparable接口,我們可以直接對這類對象進行比較排序。 舉個例子,Date Comparable的實現:
publicintcompareTo(DateanotherDate){longthisTime=getMillisOf(this);longanotherTime=getMillisOf(anotherDate);return(thisTime<anotherTime?-1:(thisTime==anotherTime?0:1));}
需要注意的是,當我們自己去實現Comparable接口時,一定要注意與**equals()**方法保持一致。當兩個對象是equals的,compare的結果應該是相等的。
還是先看代碼,看看接口定義吧:
packagejava.util;@FunctionalInterfacepublicinterfaceComparator<T>{intcompare(To1,To2);}
它是一個函數式接口,它的compare方法有兩個參數,代表進行比較的兩個對象。這個接口代表了可以作為某種對象比較的一種法則,或叫一種策略。 它的返回值正負代表意義與Comparable接口的方法一樣。 它的使用通常會有三種方式:
實現類
匿名類
Lambda表達式
在Java8之后,我們一般用Lambda比較多,也比較靈活優雅。
兩個接口功能都是用于比較排序,但其實有很大的區別。
兩者方法參數不同,Comparable只有一個參數,表示被比較的對象,因為它的方法是位于需要比較的類里的,所以只要一個參數就可以了;而Comparator的比較方法則有兩個參數,分別表示比較對象和被比較對象。
Comparable與對象綁定,位于對象內,我們可以稱之為內比較器;而Comparator是獨立于需要比較的類的,我們可以稱為外比較器。
當類實現了Comparable方法后,比較法則就確定了,我們稱之為自然比較方法,我們無法給它實現多種比較方法;而因為Comparator獨立于外,我們可以為同一個類提供多種Comparator的實現,這樣來提供多種比較方法/策略,如升序倒序,因此我們也可以將Comparator看成是一種策略模式。
相對于Comparable,Comparator有一定的靈活性,假如一個類并沒有實現Comparable接口,并且這個類是無法修改的,我們就要通過提供Comparator來進行比較排序。 Comparator這種模式實現了數據與算法的解耦合,對于維護也是很方便的。
十分友好的是,JDK為我們提供了工具類,它們的靜態方法可以幫助我們直接對數組和List進行排序。
Arrays的sort方法可以對已經實現了Comparable接口的進行排序,同時還可指定排序的范圍。
//Arrays.sort對String進行排序String[]strings={"de","dc","aA","As","k","b"};Arrays.sort(strings);assertTrue(Arrays.equals(strings,newString[]{"As","aA","b","dc","de","k"}));
指定范圍排序,需要注意的是,index是從0開始算的,包含fromIndex,不包含toIndex:
//Arrays.sort指定范圍排序strings=newString[]{"z","a","d","b"};Arrays.sort(strings,0,3);assertTrue(Arrays.equals(strings,newString[]{"a","d","z","b"}));
對于基本類型,一樣可以進行排序,并不需要使用封裝類:
//Arrays.sort對基本類型排序int[]nums={3,1,20,2,38,2,94};Arrays.sort(nums);assertTrue(Arrays.equals(nums,newint[]{1,2,2,3,20,38,94}));
還能多線程進行排序,其實是拆分成多個子數組再進行排序,最終再合并結果。
//Arrays.parallelSort多線程排序nums=newint[]{3,1,20,2,38,2,94};Arrays.parallelSort(nums);assertTrue(Arrays.equals(nums,newint[]{1,2,2,3,20,38,94}));
對于沒有實現Comparable的類也可以使用,但需要提供Comparator來指定比較策略。 本文的沒有實現Comparable接口的類Person如下:
importlombok.AllArgsConstructor;importlombok.Data;@Data@AllArgsConstructorpublicclassPerson{privateStringname;privateintage;}
排序:
//Arrays.sort提供Comparator進行排序Person[]persons=newPerson[]{newPerson("Larry",18),newPerson("David",30),newPerson("James",20),newPerson("Harry",18)};Arrays.sort(persons,Comparator.comparingInt(Person::getAge));assertTrue(Arrays.equals(persons,newPerson[]{newPerson("Larry",18),newPerson("Harry",18),newPerson("James",20),newPerson("David",30)}));
JDK的Collections工具類提供了排序方法,可以方便使用。 對于實現Comparable的類進行排序:
//Collections.sort對于實現Comparable的類進行排序List<String>names=asList("Larry","Harry","James","David");Collections.sort(names);assertEquals(names,asList("David","Harry","James","Larry"));
提供Comparator進行排序:
//Collections.sort提供Comparator進行排序List<Person>persons2=asList(newPerson("Larry",18),newPerson("David",30),newPerson("James",20),newPerson("Harry",18));Collections.sort(persons2,Comparator.comparingInt(Person::getAge));assertEquals(persons2,asList(newPerson("Larry",18),newPerson("Harry",18),newPerson("James",20),newPerson("David",30)));
反序:只是把List反過來,并不代表一定是按照大小順序的:
//Collections.reverse反序names=asList("Larry","Harry","James","David");Collections.reverse(names);assertEquals(names,asList("David","James","Harry","Larry"));
List接口有sort(Comparator<? super E> c)方法,可以實現對自身的排序,會影響自身的順序。
//List.sort排序names=asList("Larry","Harry","James","David");names.sort(Comparator.naturalOrder());assertEquals(names,asList("David","Harry","James","Larry"));
Stream提供了sorted()和sorted(Comparator<? super T> comparator)進行排序,會返回一個新的Stream。
//Stream.sorted排序names=asList("Larry","Harry","James","David");List<String>result=names.stream().sorted().collect(Collectors.toList());assertEquals(result,asList("David","Harry","James","Larry"));//Stream.sorted提供Comparator排序names=asList("Larry","Harry","James","David");result=names.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());assertEquals(result,asList("David","Harry","James","Larry"));
對類的單字段進行排序很簡單,只要提供形如:
Comparator.comparing(類名::屬性getter)
的Comparator就行了。如果需要倒序,就需要:
Comparator.comparing(類名::屬性getter).reversed()
或Comparator.comparing(類名::屬性getter, Comparator.reverseorder())。
具體代碼使用(為了不破壞List的原有順序,我們都使用Stream來操作):
//單字段排序-升序List<Person>personList=asList(newPerson("Larry",18),newPerson("David",30),newPerson("David",3),newPerson("James",20),newPerson("Harry",18));List<Person>personResult=personList.stream().sorted(Comparator.comparing(Person::getName)).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("David",30),newPerson("David",3),newPerson("Harry",18),newPerson("James",20),newPerson("Larry",18)));//單字段排序-倒序1personResult=personList.stream().sorted(Comparator.comparing(Person::getName).reversed()).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("Larry",18),newPerson("James",20),newPerson("Harry",18),newPerson("David",30),newPerson("David",3)));//單字段排序-倒序2personResult=personList.stream().sorted(Comparator.comparing(Person::getName,Comparator.reverseOrder())).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("Larry",18),newPerson("James",20),newPerson("Harry",18),newPerson("David",30),newPerson("David",3)));
多字段其實也很方便,只需要用thenComparing進行連接就可以: Comparator.comparing(類名::屬性一getter).thenComparing(類名::屬性二getter) 具體代碼使用例子如下:
//多字段排序-1升2升personResult=personList.stream().sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge)).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("David",3),newPerson("David",30),newPerson("Harry",18),newPerson("James",20),newPerson("Larry",18)));//多字段排序-1升2倒personResult=personList.stream().sorted(Comparator.comparing(Person::getName).thenComparing(Person::getAge,Comparator.reverseOrder())).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("David",30),newPerson("David",3),newPerson("Harry",18),newPerson("James",20),newPerson("Larry",18)));//多字段排序-1倒2升personResult=personList.stream().sorted(Comparator.comparing(Person::getName,Comparator.reverseOrder()).thenComparing(Person::getAge)).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("Larry",18),newPerson("James",20),newPerson("Harry",18),newPerson("David",3),newPerson("David",30)));//多字段排序-1倒2倒personResult=personList.stream().sorted(Comparator.comparing(Person::getName,Comparator.reverseOrder()).thenComparing(Person::getAge,Comparator.reverseOrder())).collect(Collectors.toList());assertEquals(personResult,asList(newPerson("Larry",18),newPerson("James",20),newPerson("Harry",18),newPerson("David",30),newPerson("David",3)));
感謝各位的閱讀,以上就是“Java中Sorting知識點有哪些”的內容了,經過本文的學習后,相信大家對Java中Sorting知識點有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是本站,小編將為大家推送更多相關知識點的文章,歡迎關注!
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
微信開放社區宣布2021年5月20日之后不再提供“小程序開啟app技術服務”(圖片來源于互聯網)(圖片來自網絡)微信方面表示,微信小程序為開發者提供打開app的技術服務,希望通過開發者的合理應用,能夠為微信用戶提供更好的體驗。平臺在鼓勵小程序提供優質內容和服務的同時,也非常注重用戶在小程序中的流暢體驗。最近收到大量用戶投訴。在小程序使用過程中,正常使用進程被屏蔽,被引導跳轉到app,嚴重影響了小程...
中國工商銀行怎么查余額?在工行進行余額查詢的方法有哪些?一起隨小編簡單了解下吧!作為宇宙第一大行,中國工商銀行的客戶有很多,如果你辦理中國工商銀行卡想要查余額,可以通過以下幾種途徑:1、網銀查詢登陸個人工商銀行網銀,通過我的賬戶-余額查詢-余額,便可查詢到銀行卡內的余額。2、微信公眾號查詢關注微信公眾號“中國工商銀行電子銀行”,在我的-余額中可查詢,需要提前綁卡。3、中國工...
郵政銀行信用卡怎么申請?【1】官網申請在百度瀏覽器中搜索并直接進入中國郵政儲蓄銀行官網,選擇“信用卡”欄目,跳轉頁面后選擇“我要辦卡”,再根據自身的喜好選擇要辦理的信用卡種類,根據頁面提示填寫申請信息,最后提交申請即可?!?】公眾號申請登錄微信,在搜索框查找“中國郵政儲蓄銀行”并關注,點擊“郵金融”,在...