成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我們一起實戰(zhàn)學習Java8 Stream新特性

開發(fā) 前端
sorted方法的入?yún)⑹且粋€比較器Comparator,這里我們直接使用Comparator.comparing方法構(gòu)建一個根據(jù)價格排序的比較器,并使用reversed方法返回一個降序的比較器。最后我們使用終結(jié)方法collect(Collectors.toList())將結(jié)果收集到集合當中。

引言

大家好,我是了不起。剛剛不久Java23如期發(fā)布,但目前國內(nèi)市場Java8還是占據(jù)著主導地位。今天我將模擬實際工作中的需求,帶領(lǐng)大家學習Java8中的Stream新特性,大家可以收藏起來以防在需要的時候找不到。

實體類聲明

@Getter
@Setter
public class ComputerDTO {
    /**
     * 計算機編號
     */
    private String computerNo;
    /**
     * 品牌
     */
    private String brand;
    /**
     * 價格
     */
    private BigDecimal price;
    /**
     * cpu核數(shù)
     */
    private Integer coreQuantity;
    /**
     * 內(nèi)存GB
     */
    private Integer memory;
    /**
     * 硬盤信息,包含容量和類型,如 "500GB HDD" 或 "256GB SSD"
     */
    private String hardDisk;
    /**
     * 產(chǎn)地
     */
    private String place;
}

場景描述

我暫且充當一下產(chǎn)品經(jīng)理,現(xiàn)在羅列出了下列需求,基本上覆蓋了日常使用Stream流的大多場景,各位小伙伴可以先行看一看有沒有思路。

經(jīng)典場景

  1. 篩選出所有品牌為“abc”的電腦,并按價格降序排序。
  2. 計算所有電腦的價格總和。
  3. 找出內(nèi)存最大的電腦的信息。
  4. 統(tǒng)計硬盤類型為SSD的電腦數(shù)量。
  5. 將所有電腦的產(chǎn)地轉(zhuǎn)換成一個不重復的集合。
  6. 創(chuàng)建一個Map,鍵為品牌,值為該品牌的電腦列表。
  7. 獲取每個品牌的平均價格。
  8. 獲取一個Map,鍵為計算機編號,值為該計算機信息。

組合應用

  1. 篩選出價格低于5000元且CPU核數(shù)大于等于4的電腦。
  2. 找出每個品牌中最貴的電腦,并返回一個包含這些電腦的列表。
  3. 統(tǒng)計每個品牌的電腦數(shù)量,并按數(shù)量降序排序。
  4. 找出所有品牌為“abc”且內(nèi)存大于等于8GB的電腦,并按CPU核數(shù)降序排序。
  5. 統(tǒng)計每個品牌的平均價格,并找出平均價格最高的品牌。
  6. 創(chuàng)建一個Map,鍵為品牌,值為該品牌所有電腦的總價。

經(jīng)典場景實戰(zhàn)攻克

下面我來帶大家一道一道攻克,并在這個過程中帶大家梳理一下Stream流使用過程中的一些注意事項。

我們假設需要處理的數(shù)據(jù)是一個ComputerDTO的List,如下:

List<ComputerDTO> computers=getComputers();

Stream流模型的操作很豐富,我們今天將使用到一些常用的方法,這些方法可以被分成兩種。

終結(jié)方法:返回值類型不再是Stream類型的方法,不再支持鏈式調(diào)用。如count、forEach、collect方法等。

非終結(jié)方法:返回值類型仍然是Stream類型的方法,支持鏈式調(diào)用。如map、filter、sorted方法等。

場景1

篩選出所有品牌為“abc”的電腦,并按價格降序排序。

List<ComputerDTO> abcComputers = computers.stream()
       .filter(computer -> "abc".equals(computer.getBrand()))
       .sorted(Comparator.comparing(ComputerDTO::getPrice).reversed())
       .collect(Collectors.toList());

首先我們將這個場景拆解成兩個過程,第一個過程是將列表中的所有品牌不為“abc”的電腦過濾掉,這里我們需要使用到filter方法。

filter方法的入?yún)⑹呛粋€參數(shù)返回結(jié)果為boolean類型的函數(shù)式接口,這里我們直接使用lambda表達式實現(xiàn)。

需要注意的是filter方法將會保留符合表達式的數(shù)據(jù),這里可以和集合的removeIf方法進行對比記憶,并且我們使用stream處理數(shù)據(jù)并不會改變原集合computers。

第二個過程是將過濾后的結(jié)果按照價格降序排序,這里我們使用sorted方法實現(xiàn)。

sorted方法的入?yún)⑹且粋€比較器Comparator,這里我們直接使用Comparator.comparing方法構(gòu)建一個根據(jù)價格排序的比較器,并使用reversed方法返回一個降序的比較器。

最后我們使用終結(jié)方法collect(Collectors.toList())將結(jié)果收集到集合當中。

場景2

計算所有電腦的價格總和。

BigDecimal totalCost = computers.stream()
       .map(ComputerDTO::getPrice)
       .reduce(BigDecimal.ZERO, BigDecimal::add);

這個場景我們需要先將集合中的ComputerDTO對象轉(zhuǎn)換為價格,因為我們需要的最終結(jié)果是一個BigDecimal類型,所以需要先使用map方法對數(shù)據(jù)進行轉(zhuǎn)換。

map方法的入?yún)⑹且粋€Function函數(shù)式接口,下面貼出一張圖幫助大家理解map方法的作用。

圖片圖片

map方法在工作中常常被使用,例如需要根據(jù)一個實體類集合獲取一個屬性值集合,通常先使用map方法獲取屬性值,看情況需要可以使用distinct方法去重、filter過濾、sorted方法排序,最后使用collect方法收集起來。

在當前場景中我們需要計算所有電腦的價格總和,所以可以使用reduce終結(jié)方法進行匯總。

圖片圖片

場景3

找出內(nèi)存最大的電腦的信息。

Optional<ComputerDTO> maxMemoryComputer = computers.stream()
       .max(Comparator.comparingInt(ComputerDTO::getMemory));

這個場景簡單粗暴,直接將待處理數(shù)據(jù)轉(zhuǎn)成流,然后使用max方法就可以解決,不過需要注意的是max方法返回的數(shù)據(jù)使用Optional包了一層。

Optional類同樣是Java8提供的,使用isPresent方法可以判斷包含值是否為null,通過get方法可以獲取包含值,如果包含值為null會拋出一個NoSuchElementException異常,所以通常搭配isPresent方法使用。

場景4

統(tǒng)計硬盤類型為SSD的電腦數(shù)量。

long ssdCount = computers.stream()
       .filter(computer -> computer.getHardDisk().contains("SSD"))
       .count();

這個場景使用了一個新的終結(jié)方法count,count方法用于統(tǒng)計流中元素個數(shù),返回值類型為long類型。

場景5

將所有電腦的產(chǎn)地轉(zhuǎn)換成一個不重復的集合。

Set<String> places = computers.stream()
       .map(ComputerDTO::getPlace)
       .collect(Collectors.toSet());

這個場景在工作中常常會用到,也是上面提到的map的經(jīng)典用法,只不過這里將流中數(shù)據(jù)通過collect(Collectors.toSet())收集到了Set中,利用了Set的特性進行去重,而沒有使用distinct方法進行去重。

這里引申一下,上點難度,如果這里最終需要獲取的是根據(jù)產(chǎn)地去重后的ComputerDTO集合呢,使用流的方式又該怎樣實現(xiàn)。

這是工作中另外的一個經(jīng)典場景,List集合按照對象屬性去重,其實最終也是利用了Set的特性,在Set的構(gòu)造函數(shù)中傳入了自定義比較器!

List<ComputerDTO> newList = computers.stream().collect(Collectors
                .collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ComputerDTO::getPlace)))
                        , ArrayList::new));

這里使用的Collectors.collectingAndThen方法只是將返回結(jié)果Set轉(zhuǎn)化為了List,核心處理就是Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ComputerDTO::getPlace)))。

場景6

創(chuàng)建一個Map,鍵為品牌,值為該品牌的電腦列表。

Map<String, List<ComputerDTO>> computersByBrand = computers.stream()
       .collect(Collectors.groupingBy(ComputerDTO::getBrand));

這個場景也是工作中常常會遇到的場景,對原有數(shù)據(jù)根據(jù)某一個緯度進行分組,然后不同組的數(shù)據(jù)使用不同的邏輯進行處理。Stream為這個需求也提供了專門的方法Collectors.groupingBy。

場景7

獲取每個品牌的平均價格。

Map<String, Double> averagePrices = computers.stream()
       .collect(Collectors.groupingBy(ComputerDTO::getBrand, Collectors.averagingDouble(c -> c.getPrice().doubleValue())));

這個場景是場景6的進階玩法,根據(jù)某一個緯度進行分組,分組后再對數(shù)據(jù)進行處理。

這里使用的是Collectors.groupingBy兩個參數(shù)的重載方法。

場景8

獲取一個Map,鍵為計算機編號,值為該計算機信息。

Map<String, ComputerDTO> computerInfoMap = computers.stream().collect(Collectors.toMap(ComputerDTO::getComputerNo, item -> item));

Map<String, ComputerDTO> computerInfoMap = computers.stream().collect(HashMap::new, (m, v) -> m.put(v.getComputerNo(), v), HashMap::putAll);

這個場景在工作中出現(xiàn)的頻率很高,通常有兩種方法去實現(xiàn),其中Collectors.toMap方法有一個小坑,大家在使用時需要注意一下。

java8的Collectors.toMap的value不能為null。

如果待處理的數(shù)據(jù)中value值存在null,則會出現(xiàn)莫名其妙的空指針異常,所以我在工作中往往會使用第二種方式。

組合應用代碼參考

通過上面經(jīng)典場景的講解,其實我們可以注意到,基本上絕大多數(shù)的應用都離不開collect方法,這個方法在流的使用中極為重要,在后續(xù)的文章中我也會為大家進一步的講解collect方法,敬請期待!

組合場景就是對經(jīng)典場景中的一些常用API進行組合應用,所以就不在這里一一贅述,僅為大家提供了參考代碼。

  1. 篩選出價格低于5000元且CPU核數(shù)大于等于4的電腦。
List<ComputerDTO> affordableAndPowerful = computers.stream()
       .filter(computer -> computer.getPrice().compareTo(new BigDecimal("5000")) < 0 && computer.getCoreQuantity() >= 4)
       .collect(Collectors.toList());
  1. 找出每個品牌中最貴的電腦,并返回一個包含這些電腦的列表。
Map<String, ComputerDTO> mostExpensivePerBrand = computers.stream()
            .collect(Collectors.groupingBy(ComputerDTO::getBrand,
                    Collectors.collectingAndThen(
                            Collectors.maxBy(Comparator.comparing(ComputerDTO::getPrice)),
                            optional -> optional.orElseThrow(() -> new NoSuchElementException("No computers found for this brand"))
       )
   ));

    List<ComputerDTO> mostExpensiveComputers = new ArrayList<>(mostExpensivePerBrand.values());
  1. 統(tǒng)計每個品牌的電腦數(shù)量,并按數(shù)量降序排序。
Map<String, Long> brandCounts = computers.stream()
       .collect(Collectors.groupingBy(ComputerDTO::getBrand, Collectors.counting()));

   List<Map.Entry<String, Long>> sortedBrandCounts = brandCounts.entrySet().stream()
       .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
       .collect(Collectors.toList());
  1. 找出所有品牌為“abc”且內(nèi)存大于等于8GB的電腦,并按CPU核數(shù)降序排序。
List<ComputerDTO> abcHighMemoryComputers = computers.stream()
       .filter(computer -> "abc".equals(computer.getBrand()) && computer.getMemory() >= 8)
       .sorted(Comparator.comparingInt(ComputerDTO::getCoreQuantity).reversed())
       .collect(Collectors.toList());
  1. 統(tǒng)計每個品牌的平均價格,并找出平均價格最高的品牌。
Optional<Map.Entry<String, Double>> highestAveragePrice = computers.stream()
       .collect(Collectors.groupingBy(
           ComputerDTO::getBrand,
           Collectors.averagingDouble(c -> c.getPrice().doubleValue())
       ))
       .entrySet().stream()
       .max(Map.Entry.comparingByValue());

   String highestBrand = highestAveragePrice.map(Map.Entry::getKey).orElse(null);
   double highestAverage = highestAveragePrice.map(Map.Entry::getValue).orElse(0.0);
  1. 創(chuàng)建一個Map,鍵為品牌,值為該品牌所有電腦的總價。
Map<String, BigDecimal> totalPricesByBrand = computers.stream()
       .collect(Collectors.groupingBy(
           ComputerDTO::getBrand,
           Collectors.reducing(BigDecimal.ZERO, ComputerDTO::getPrice, BigDecimal::add)
       ));

結(jié)語

學會使用java8的Stream新特性,可以極大的減少工作中的代碼量,可以使自己的代碼看起來更整潔,同時很多框架源碼中也大量使用Stream,掌握了它也可以為我們閱讀源碼提供幫助,希望這篇文章可以給大家?guī)韼椭?/p>

責任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2021-05-19 10:37:16

WebFlux 前置工具

2022-02-14 10:16:22

Axios接口HTTP

2022-12-30 09:24:23

Java8Stream操作

2022-12-09 07:48:10

Java8Stream表達式

2021-11-26 09:44:42

鏈表節(jié)點定位

2021-05-20 07:15:34

RSA-PSS算法簽名

2022-12-01 09:59:57

內(nèi)核觀測性方法

2023-03-28 07:32:37

2023-03-26 12:45:52

Linux內(nèi)核頭文件

2025-03-27 02:00:00

SPIJava接口

2022-07-29 08:17:46

Java對象內(nèi)存

2023-09-29 08:58:38

2023-09-15 06:56:01

RC.NET 6Release

2021-10-11 10:25:33

排列nums數(shù)組

2021-03-18 00:04:13

C# 類型數(shù)據(jù)

2022-03-31 18:59:43

數(shù)據(jù)庫InnoDBMySQL

2023-08-10 08:28:46

網(wǎng)絡編程通信

2021-08-27 07:06:09

DubboDocker技術(shù)

2021-01-12 05:08:49

DHCP協(xié)議模型

2022-10-18 07:33:57

Maven構(gòu)建工具
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产精品毛片一区二区三区 | 国产精品视频一区二区三 | 在线久草 | 久久久久久九九九九九九 | 在线精品一区 | 中国一级特黄真人毛片 | 日韩中文字幕在线 | 香蕉91| 精品视频久久久 | 国产在线视频一区二区董小宛性色 | 国产精品不卡 | 国产精品福利在线 | 亚洲免费av一区 | 久久国产精品视频观看 | 亚洲精品一区二三区不卡 | 91视频导航| 日韩欧美在线视频观看 | 黄久久久 | 欧美视频一区 | 91佛爷在线观看 | 成人在线免费观看视频 | 国产精品一区二区日韩 | 亚洲第一成人影院 | 黄色香蕉视频在线观看 | 毛片一区二区三区 | 午夜丁香视频在线观看 | 精品成人一区二区 | 视频一区二区在线 | 中文字幕成人av | 亚洲精品在线视频 | 一本大道久久a久久精二百 欧洲一区二区三区 | 欧美日批| 欧美精品一区二区在线观看 | 少妇午夜一级艳片欧美精品 | 国产精品日韩欧美一区二区 | 午夜精品久久久久久久久久久久久 | 中文字幕在线观看成人 | 日日干夜夜操天天操 | 91影院在线观看 | 亚洲欧美精品久久 | 亚洲精品久久久久久久久久久久久 |