最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java8如何使用Lambda表達(dá)式進(jìn)行比較

 更新時(shí)間:2022年01月26日 09:36:47   作者:老K的Java博客  
Lambda表達(dá)式,也可稱為閉包,是java8的新特性,作用是取代大部分內(nèi)部類,優(yōu)化java代碼結(jié)構(gòu),讓代碼變得更加簡(jiǎn)潔緊湊。本文將利用Lambda表達(dá)式進(jìn)行排序比較,需要的可以參考一下

在Java 8之前,對(duì)集合進(jìn)行排序需要為排序中使用的比較器 Comparator 創(chuàng)建一個(gè)匿名內(nèi)部類:

new Comparator<Human>() {
    @Override
    public int compare(Human h1, Human h2) {
        return h1.getName().compareTo(h2.getName());
    }
}

這僅用于對(duì) Human 實(shí)體列表進(jìn)行排序:

@Test
public void givenPreLambda_whenSortingEntitiesByName_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 10), 
      new Human("Jack", 12)
    );
    
    Collections.sort(humans, new Comparator<Human>() {
        @Override
        public int compare(Human h1, Human h2) {
            return h1.getName().compareTo(h2.getName());
        }
    });
    Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}

支持Lambda的基本排序

隨著Lambdas的引入,我們現(xiàn)在可以繞過(guò)匿名內(nèi)部類,通過(guò)簡(jiǎn)單的函數(shù)語(yǔ)義實(shí)現(xiàn)相同的結(jié)果:

(final Human h1, final Human h2) -> h1.getName().compareTo(h2.getName());

類似地,我們現(xiàn)在可以像以前一樣測(cè)試行為:

@Test
public void whenSortingEntitiesByName_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 10), 
      new Human("Jack", 12)
    );
    
    humans.sort(
      (Human h1, Human h2) -> h1.getName().compareTo(h2.getName()));
 
    assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}

注意,我們還使用添加到j(luò)ava中的新排序API。 java.util.List 使用Java8而不是舊集合列出 Collections.sort 。

無(wú)類型定義的基本排序

我們可以通過(guò)不指定類型定義來(lái)進(jìn)一步簡(jiǎn)化表達(dá)式;編譯器能夠自行推斷出以下各項(xiàng):

(h1, h2) -> h1.getName().compareTo(h2.getName())

同樣,測(cè)試仍然非常相似:

@Test
public void 
  givenLambdaShortForm_whenSortingEntitiesByName_thenCorrectlySorted() {
    
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 10), 
      new Human("Jack", 12)
    );
    
    humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName()));
 
    assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}

使用引用靜態(tài)方法進(jìn)行排序

接下來(lái),我們將使用Lambda表達(dá)式和對(duì)靜態(tài)方法的引用來(lái)執(zhí)行排序。

首先,我們將使用與 Comparator<Human> 對(duì)象中的 compare 方法完全相同的簽名來(lái)定義 CompareBynametEnable 方法:

public static int compareByNameThenAge(Human lhs, Human rhs) {
    if (lhs.name.equals(rhs.name)) {
        return Integer.compare(lhs.age, rhs.age);
    } else {
        return lhs.name.compareTo(rhs.name);
    }
}

然后我們要調(diào)用 humans.sort 使用此引用的排序方法:

humans.sort(Human::compareByNameThenAge);

最終結(jié)果是使用靜態(tài)方法作為比較器對(duì)集合進(jìn)行工作排序:

@Test
public void 
  givenMethodDefinition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
    
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 10), 
      new Human("Jack", 12)
    );
    
    humans.sort(Human::compareByNameThenAge);
    Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}

Sort Extracted Comparators

通過(guò)使用實(shí)例方法引用和比較器,我們甚至可以避免定義比較邏輯本身。比較方法,該方法基于該函數(shù)提取并創(chuàng)建可比較的。

我們將使用 getName() 來(lái)構(gòu)建Lambda表達(dá)式并按名稱對(duì)列表進(jìn)行排序:

@Test
public void 
  givenInstanceMethod_whenSortingEntitiesByName_thenCorrectlySorted() {
    
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 10), 
      new Human("Jack", 12)
    );
    
    Collections.sort(
      humans, Comparator.comparing(Human::getName));
    assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}

反向排序

JDK 8還引入了一種輔助方法來(lái)反轉(zhuǎn)比較器。我們可以很快利用這一點(diǎn)來(lái)逆轉(zhuǎn)我們的排序:

@Test
public void whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 10), 
      new Human("Jack", 12)
    );
    
    Comparator<Human> comparator
      = (h1, h2) -> h1.getName().compareTo(h2.getName());
    
    humans.sort(comparator.reversed());
 
    Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
}

使用多個(gè)條件進(jìn)行排序

比較lambda表達(dá)式不必如此簡(jiǎn)單。我們還可以編寫(xiě)更復(fù)雜的表達(dá)式,例如,先按名稱,然后按年齡對(duì)實(shí)體進(jìn)行排序:

@Test
public void whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 12), 
      new Human("Sarah", 10), 
      new Human("Zack", 12)
    );
    
    humans.sort((lhs, rhs) -> {
        if (lhs.getName().equals(rhs.getName())) {
            return Integer.compare(lhs.getAge(), rhs.getAge());
        } else {
            return lhs.getName().compareTo(rhs.getName());
        }
    });
    Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
}

使用多個(gè)條件排序-組合

同樣的比較邏輯,首先按名稱排序,然后按年齡排序,也可以通過(guò)新的composition支持來(lái)實(shí)現(xiàn)。

從JDK 8開(kāi)始,我們現(xiàn)在可以將多個(gè)比較器鏈接在一起,以構(gòu)建更復(fù)雜的比較邏輯:

@Test
public void 
  givenComposition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
    
    List<Human> humans = Lists.newArrayList(
      new Human("Sarah", 12), 
      new Human("Sarah", 10), 
      new Human("Zack", 12)
    );

    humans.sort(
      Comparator.comparing(Human::getName).thenComparing(Human::getAge)
    );
    
    Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
}

使用Stream.sorted()對(duì)列表進(jìn)行排序

我們還可以使用Java 8的Stream sorted()API對(duì)集合進(jìn)行排序。

我們可以使用自然排序以及比較器提供的排序?qū)α鬟M(jìn)行排序。為此,我們有兩個(gè)sorted()API的重載變體:

  • sorted()–使用自然排序?qū)α鞯脑剡M(jìn)行排序;元素類必須實(shí)現(xiàn)可比較的接口。
  • sorted(Comparator<? super T> comparator)–基于Comparator實(shí)例對(duì)元素進(jìn)行排序

讓我們看一個(gè)如何將sorted()方法用于自然排序的示例:

@Test
public final void 
  givenStreamNaturalOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
    List<String> letters = Lists.newArrayList("B", "A", "C");
	
    List<String> sortedLetters = letters.stream().sorted().collect(Collectors.toList());
    assertThat(sortedLetters.get(0), equalTo("A"));
}

現(xiàn)在,讓我們看看如何在 sorted() API中使用自定義比較器:

@Test
public final void 
  givenStreamCustomOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {	
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
    Comparator<Human> nameComparator = (h1, h2) -> h1.getName().compareTo(h2.getName());
	
    List<Human> sortedHumans = 
      humans.stream().sorted(nameComparator).collect(Collectors.toList());
    assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12)));
}

如果使用比較器,我們可以進(jìn)一步簡(jiǎn)化上述示例。 Comparator.comparing() 方法:

@Test
public final void 
  givenStreamComparatorOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
 
    List<Human> sortedHumans = humans.stream()
      .sorted(Comparator.comparing(Human::getName))
      .collect(Collectors.toList());
      
    assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12)));
}

使用Stream.sorted()對(duì)列表進(jìn)行反向排序

我們也可以使用 Stream.sorted() 對(duì)集合進(jìn)行反向排序。

首先,讓我們看一個(gè)如何將sorted()方法與Comparator相結(jié)合的示例。reverseOrder()按與自然順序相反的順序?qū)α斜砼判颍?/p>

@Test
public final void 
  givenStreamNaturalOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
    List<String> letters = Lists.newArrayList("B", "A", "C");

    List<String> reverseSortedLetters = letters.stream()
      .sorted(Comparator.reverseOrder())
      .collect(Collectors.toList());
      
    assertThat(reverseSortedLetters.get(0), equalTo("C"));
}

現(xiàn)在讓我們看看如何使用sorted()方法和自定義比較器:

@Test
public final void 
  givenStreamCustomOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
    Comparator<Human> reverseNameComparator = 
      (h1, h2) -> h2.getName().compareTo(h1.getName());

    List<Human> reverseSortedHumans = humans.stream().sorted(reverseNameComparator)
      .collect(Collectors.toList());
    assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10)));
}

請(qǐng)注意,compareTo的調(diào)用是翻轉(zhuǎn)的,它負(fù)責(zé)反轉(zhuǎn)。

最后,讓我們使用比較器簡(jiǎn)化上述示例。Comparator.comparing() 方法:

@Test
public final void 
  givenStreamComparatorOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
    List<Human> humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));

    List<Human> reverseSortedHumans = humans.stream()
      .sorted(Comparator.comparing(Human::getName, Comparator.reverseOrder()))
      .collect(Collectors.toList());
    
    assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10)));
}

Null值

到目前為止,我們實(shí)現(xiàn)的比較器不能對(duì)包含空值的集合進(jìn)行排序。也就是說(shuō),如果集合至少包含一個(gè)null元素,則sort方法會(huì)引發(fā) NullPointerException :

@Test(expected = NullPointerException.class)
public void givenANullElement_whenSortingEntitiesByName_thenThrowsNPE() {
    List<Human> humans = Lists.newArrayList(null, new Human("Jack", 12));

    humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName()));
}

最簡(jiǎn)單的解決方案是在比較器實(shí)現(xiàn)中手動(dòng)處理空值:

@Test
public void givenANullElement_whenSortingEntitiesByNameManually_thenMovesTheNullToLast() {
    List<Human> humans = Lists.newArrayList(null, new Human("Jack", 12), null);

    humans.sort((h1, h2) -> {
        if (h1 == null) {
            return h2 == null ? 0 : 1;
        }
        else if (h2 == null) {
            return -1;
        }
        return h1.getName().compareTo(h2.getName());
    });

    Assert.assertNotNull(humans.get(0));
    Assert.assertNull(humans.get(1));
    Assert.assertNull(humans.get(2));
}

在這里,我們將所有空元素推向集合的末尾。為此,比較器將null視為大于非null值。如果兩者都為空,則認(rèn)為它們相等。

此外,我們可以將任何非空安全的比較器 Comparator.nullsLast() 方法,并獲得相同的結(jié)果:

@Test
public void givenANullElement_whenSortingEntitiesByName_thenMovesTheNullToLast() {
    List<Human> humans = Lists.newArrayList(null, new Human("Jack", 12), null);

    humans.sort(Comparator.nullsLast(Comparator.comparing(Human::getName)));

    Assert.assertNotNull(humans.get(0));
    Assert.assertNull(humans.get(1));
    Assert.assertNull(humans.get(2));
}

同樣,我們可以使用 Comparator.nullsFirst() 將null元素移到集合的開(kāi)頭:

@Test
public void givenANullElement_whenSortingEntitiesByName_thenMovesTheNullToStart() {
    List<Human> humans = Lists.newArrayList(null, new Human("Jack", 12), null);

    humans.sort(Comparator.nullsFirst(Comparator.comparing(Human::getName)));

    Assert.assertNull(humans.get(0));
    Assert.assertNull(humans.get(1));
    Assert.assertNotNull(humans.get(2));
}

強(qiáng)烈建議使用 nullsFirst() 或 nullsLast() 修飾符,因?yàn)樗鼈兏`活、可讀性更強(qiáng)。

結(jié)論

本文演示了使用Java8 Lambda表達(dá)式對(duì)列表進(jìn)行排序的各種令人興奮的方式,這些方式超越了語(yǔ)法糖,轉(zhuǎn)變?yōu)檎嬲龔?qiáng)大的函數(shù)語(yǔ)義。

所有這些示例和代碼片段的實(shí)現(xiàn)都可以在GitHub上找到: https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-lambdas

到此這篇關(guān)于詳解Java8如何使用Lambda表達(dá)式進(jìn)行比較的文章就介紹到這了,更多相關(guān)Java8 Lambda表達(dá)式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot詳解如果通過(guò)@Value注解給靜態(tài)變量注入值

    SpringBoot詳解如果通過(guò)@Value注解給靜態(tài)變量注入值

    這篇文章主要介紹了springboot如何通過(guò)@Value給靜態(tài)變量注入值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • common-upload上傳文件功能封裝類分享

    common-upload上傳文件功能封裝類分享

    本文介紹一個(gè)common-upload上傳封裝類,為了更方便的上傳文件,對(duì)common-upload進(jìn)行了一個(gè)簡(jiǎn)單的封裝,大家參考使用吧
    2014-01-01
  • Mybatis中SQL的執(zhí)行過(guò)程詳解

    Mybatis中SQL的執(zhí)行過(guò)程詳解

    MyBatis框架通過(guò)映射文件或注解將Java代碼中的方法與數(shù)據(jù)庫(kù)操作進(jìn)行映射,執(zhí)行過(guò)程包括SQL解析、參數(shù)綁定、SQL預(yù)編譯、執(zhí)行、結(jié)果映射、事務(wù)處理、緩存處理和日志記錄
    2024-12-12
  • Springboot使用jsp具體案例解析

    Springboot使用jsp具體案例解析

    這篇文章主要介紹了Springboot使用jsp具體案例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 列舉java語(yǔ)言中反射的常用方法及實(shí)例代碼

    列舉java語(yǔ)言中反射的常用方法及實(shí)例代碼

    反射機(jī)制指的是程序在運(yùn)行時(shí)能夠獲取自身的信息。這篇文章主要介紹了列舉java語(yǔ)言中反射的常用方法,需要的朋友可以參考下
    2019-07-07
  • java如何判斷一個(gè)數(shù)是否是素?cái)?shù)(質(zhì)數(shù))

    java如何判斷一個(gè)數(shù)是否是素?cái)?shù)(質(zhì)數(shù))

    這篇文章主要介紹了java如何判斷一個(gè)數(shù)是否是素?cái)?shù)(質(zhì)數(shù)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java 注冊(cè)時(shí)發(fā)送激活郵件和激活的實(shí)現(xiàn)示例

    Java 注冊(cè)時(shí)發(fā)送激活郵件和激活的實(shí)現(xiàn)示例

    這篇文章主要介紹了Java 注冊(cè)時(shí)發(fā)送激活郵件和激活的實(shí)現(xiàn)示例的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • dubbo新手學(xué)習(xí)之事件通知實(shí)踐教程

    dubbo新手學(xué)習(xí)之事件通知實(shí)踐教程

    這篇文章主要給大家介紹了關(guān)于dubbo新手學(xué)習(xí)之事件通知實(shí)踐的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Java中用enum結(jié)合testng實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)的方法示例

    Java中用enum結(jié)合testng實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)的方法示例

    TestNG數(shù)據(jù)驅(qū)動(dòng)提供的參數(shù)化讓我們?cè)跍y(cè)試項(xiàng)目可以靈活根據(jù)需求建立不同的dataprovider來(lái)提供數(shù)據(jù),而真正實(shí)現(xiàn)數(shù)據(jù),頁(yè)面,測(cè)試彼此獨(dú)立而又有機(jī)結(jié)合的可能性。 下面這篇文章主要給大家介紹了Java中用enum和testng做數(shù)據(jù)驅(qū)動(dòng)的方法示例,需要的朋友可以參考借鑒。
    2017-01-01
  • java將XML文檔轉(zhuǎn)換成json格式數(shù)據(jù)的示例

    java將XML文檔轉(zhuǎn)換成json格式數(shù)據(jù)的示例

    本篇文章主要介紹了java將XML文檔轉(zhuǎn)換成json格式數(shù)據(jù)的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12

最新評(píng)論

云林县| 云龙县| 大田县| 马边| 九寨沟县| 咸宁市| 辽源市| 馆陶县| 应城市| 宁阳县| 晋宁县| 苗栗市| 化德县| 灵台县| 阳高县| 阿克陶县| 木兰县| 夏河县| 麦盖提县| 正安县| 岢岚县| 黄陵县| 达州市| 永吉县| 佛山市| 阳朔县| 邵阳市| 台前县| 梅州市| 金门县| 淳化县| 堆龙德庆县| 海林市| 荣昌县| 长阳| 左贡县| 海南省| 辉县市| 正镶白旗| 茌平县| 五寨县|