Java 進(jìn)階使用 Lambda 表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能_第1頁(yè)
Java 進(jìn)階使用 Lambda 表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能_第2頁(yè)
Java 進(jìn)階使用 Lambda 表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能_第3頁(yè)
Java 進(jìn)階使用 Lambda 表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能_第4頁(yè)
Java 進(jìn)階使用 Lambda 表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能_第5頁(yè)
已閱讀5頁(yè),還剩9頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第Java進(jìn)階使用Lambda表達(dá)式實(shí)現(xiàn)超強(qiáng)的排序功能因?yàn)槎x的Comparator是使用name字段排序,在Java中,String類型的排序是通過單字符的ASCII碼順序判斷的,J排在T的前面,所以Jerry排在第一個(gè)。

使用Lambda表達(dá)式替換Comparator匿名內(nèi)部類

使用過Java8的Lamdba的應(yīng)該知道,匿名內(nèi)部類可以簡(jiǎn)化為L(zhǎng)ambda表達(dá)式為:

Collections.sort(students,(Studenth1,Studenth2)-h1.getName().compareTo(h2.getName()));

在Java8中,List類中增加了sort方法,所以Collections.sort可以直接替換為:

students.sort((Studenth1,Studenth2)-h1.getName().compareTo(h2.getName()));

根據(jù)Java8中Lambda的類型推斷,我們可以將指定的Student類型簡(jiǎn)寫:

students.sort((h1,h2)-h1.getName().compareTo(h2.getName()));

至此,我們整段排序邏輯可以簡(jiǎn)化為:

@Test

voidbaseSortedLambdaWithInferring(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

students.sort((h1,h2)-h1.getName().compareTo(h2.getName()));

Assertions.assertEquals(students.get(0),newStudent("Jerry",12));

通過靜態(tài)方法抽取公共的Lambda表達(dá)式

我們可以在Student中定義一個(gè)靜態(tài)方法:

publicstaticintcompareByNameThenAge(Students1,Students2){

if(.equals()){

returnIpare(s1.age,s2.age);

}else{

returnpareTo();

這個(gè)方法需要返回一個(gè)int類型參數(shù),在Java8中,我們可以在Lambda中使用該方法:

@Test

voidsortedUsingStaticMethod(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

students.sort(Student::compareByNameThenAge);

Assertions.assertEquals(students.get(0),newStudent("Jerry",12));

借助Comparator的comparing方法

在Java8中,Comparator類新增了comparing方法,可以將傳遞的Function參數(shù)作為比較元素,比如:

@Test

voidsortedUsingComparator(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

students.sort(Cparing(Student::getName));

Assertions.assertEquals(students.get(0),newStudent("Jerry",12));

多條件排序

我們?cè)陟o態(tài)方法一節(jié)中展示了多條件排序,還可以在Comparator匿名內(nèi)部類中實(shí)現(xiàn)多條件邏輯:

@Test

voidsortedMultiCondition(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12),

newStudent("Jerry",13)

students.sort((s1,s2)-{

if(s1.getName().equals(s2.getName())){

returnIpare(s1.getAge(),s2.getAge());

}else{

returns1.getName().compareTo(s2.getName());

Assertions.assertEquals(students.get(0),newStudent("Jerry",12));

從邏輯來看,多條件排序就是先判斷第一級(jí)條件,如果相等,再判斷第二級(jí)條件,依次類推。在Java8中可以使用comparing和一系列thenComparing表示多級(jí)條件判斷,上面的邏輯可以簡(jiǎn)化為:

@Test

voidsortedMultiConditionUsingComparator(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12),

newStudent("Jerry",13)

students.sort(Cparing(Student::getName).thenComparing(Student::getAge));

Assertions.assertEquals(students.get(0),newStudent("Jerry",12));

這里的thenComparing方法是可以有多個(gè)的,用于表示多級(jí)條件判斷,這也是函數(shù)式編程的方便之處。

在Stream中進(jìn)行排序

Java8中,不但引入了Lambda表達(dá)式,還引入了一個(gè)全新的流式API:StreamAPI,其中也有sorted方法用于流式計(jì)算時(shí)排序元素,可以傳入Comparator實(shí)現(xiàn)排序邏輯:

@Test

voidstreamSorted(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

finalComparatorStudentcomparator=(h1,h2)-h1.getName().compareTo(h2.getName());

finalListStudentsortedStudents=students.stream()

.sorted(comparator)

.collect(Collectors.toList());

Assertions.assertEquals(sortedStudents.get(0),newStudent("Jerry",12));

同樣的,我們可以通過Lambda簡(jiǎn)化書寫:

@Test

voidstreamSortedUsingComparator(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

finalComparatorStudentcomparator=Cparing(Student::getName);

finalListStudentsortedStudents=students.stream()

.sorted(comparator)

.collect(Collectors.toList());

Assertions.assertEquals(sortedStudents.get(0),newStudent("Jerry",12));

倒序排列

調(diào)轉(zhuǎn)排序判斷

排序就是根據(jù)compareTo方法返回的值判斷順序,如果想要倒序排列,只要將返回值取返即可:

@Test

voidsortedReverseUsingComparator2(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

finalComparatorStudentcomparator=(h1,h2)-h2.getName().compareTo(h1.getName());

students.sort(comparator);

Assertions.assertEquals(students.get(0),newStudent("Tom",10));

可以看到,正序排列的時(shí)候,我們是h1.getName().compareTo(h2.getName()),這里我們直接倒轉(zhuǎn)過來,使用的是h2.getName().compareTo(h1.getName()),也就達(dá)到了取反的效果。在Java的Collections中定義了一個(gè)java.util.Collections.ReverseComparator內(nèi)部私有類,就是通過這種方式實(shí)現(xiàn)元素反轉(zhuǎn)。

借助Comparator的reversed方法倒序

在Java8中新增了reversed方法實(shí)現(xiàn)倒序排列,用起來也是很簡(jiǎn)單:

@Test

voidsortedReverseUsingComparator(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

finalComparatorStudentcomparator=(h1,h2)-h1.getName().compareTo(h2.getName());

students.sort(comparator.reversed());

Assertions.assertEquals(students.get(0),newStudent("Tom",10));

在Cparing中定義排序反轉(zhuǎn)

comparing方法還有一個(gè)重載方法,java.util.Comparator#comparing(java.util.function.FunctionsuperT,extendsU,java.util.ComparatorsuperU),第二個(gè)參數(shù)就可以傳入Comparator.reverseOrder(),可以實(shí)現(xiàn)倒序:

@Test

voidsortedUsingComparatorReverse(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

students.sort(Cparing(Student::getName,Comparator.reverseOrder()));

Assertions.assertEquals(students.get(0),newStudent("Jerry",12));

在Stream中定義排序反轉(zhuǎn)

在Stream中的操作與直接列表排序類似,可以反轉(zhuǎn)Comparator定義,也可以使用Comparator.reverseOrder()反轉(zhuǎn)。實(shí)現(xiàn)如下:

@Test

voidstreamReverseSorted(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

finalComparatorStudentcomparator=(h1,h2)-h2.getName().compareTo(h1.getName());

finalListStudentsortedStudents=students.stream()

.sorted(comparator)

.collect(Collectors.toList());

Assertions.assertEquals(sortedStudents.get(0),newStudent("Tom",10));

@Test

voidstreamReverseSortedUsingComparator(){

finalListStudentstudents=Lists.newArrayList(

newStudent("Tom",10),

newStudent("Jerry",12)

finalListStudentsortedStudents=students.stream()

.sorted(Cparing(Student::getName,Comparator.reverseOrder()))

.collect(Collectors.toList());

Assertions.assertEquals(sortedStudents.get(0),newStudent("Tom",10));

null值的判斷

前面的例子中都是有值元素排序,能夠覆蓋大部分場(chǎng)景,但有時(shí)候我們還是會(huì)碰到元素中存在null的情況:

列表中的元素是null

列表中的元素參與排序條件的字段是null

如果還是使用前面的那些實(shí)現(xiàn),我們會(huì)碰到NullPointException異常,即NPE,簡(jiǎn)單演示一下:

@Test

voidsortedNullGotNPE(){

finalListStudentstudents=Lists.newArrayList(

null,

newStudent("Snoopy",12),

null

Assertions.assertThrows(NullPointerException.class,

()-students.sort(Cparing(Student::getName)));

所以,我們需要考慮這些場(chǎng)景。

元素是null的笨拙實(shí)現(xiàn)

最先想到的就是判空:

@Test

voidsortedNullNoNPE(){

finalListStudentstudents=Lists.newArrayList(

null,

newStudent("Snoopy",12),

null

students.sort((s1,s2)-{

if(s1==null){

returns2==null0:1;

}elseif(s2==null){

return-1;

returns1.getName().compareTo(s2.getName());

Assertions.assertNotNull(students.get(0));

Assertions.assertNull(students.get(1));

Assertions.assertNull(students.get(2));

我們可以將判空的邏輯抽取出一個(gè)Comparator,通過組合方式實(shí)現(xiàn):

classNullComparatorTimplementsComparatorT{

privatefinalComparatorTreal;

NullComparator(ComparatorsuperTreal){

this.real=(ComparatorT)real;

@Override

publicintcompare(Ta,Tb){

if(a==null){

return(b==null)0:1;

}elseif(b==null){

return-1;

}else{

return(real==null)0:pare(a,b);

在Java8中已經(jīng)為我們準(zhǔn)備了這個(gè)實(shí)現(xiàn)。

使用Comparator.nullsLast和Comparator.nullsFirst

使用Comparator.nullsLast實(shí)現(xiàn)null在結(jié)尾:

@Test

voidsortedNullLast(){

finalListStudentstudents=Lists.newArrayList(

null,

newStudent("Snoopy",12),

null

students.sort(Comparator.nullsLast(Cparing(Student::getName)));

Assertions.assertNotNull(students.get(0));

Assertions.assertNull(students.get(1));

Assertions.assertNull(students.get(2));

使用Comparator.nullsFirst實(shí)現(xiàn)null在開頭:

@Test

voidsortedNullFirst(){

finalListStudentstudents=Lists.newArrayList(

null,

newStudent("Snoopy",12),

null

students.sort(Comparator.nullsFirst(Cparing(Student::getName)));

Assertions.assertNull(students.get(0));

Assertions.assertNull(students.get(1));

Assertions.assertNotNull(students.get(2));

是不是很簡(jiǎn)單,接下來我們看下如何實(shí)現(xiàn)排序條件的字段是null的邏輯。

排序條件的字段是nu

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論