亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺聊java8中數(shù)值流的使用

 更新時(shí)間:2023年10月27日 15:37:29   作者:shark_chili  
java8為我提供的簡(jiǎn)單快捷的數(shù)值流計(jì)算API,本文就基于幾個(gè)常見(jiàn)的場(chǎng)景介紹一下數(shù)值流API的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下

簡(jiǎn)介

java8為我提供的簡(jiǎn)單快捷的數(shù)值流計(jì)算API,本文就基于幾個(gè)常見(jiàn)的場(chǎng)景介紹一下數(shù)值流API的使用。

基礎(chǔ)示例

我們以一個(gè)食物熱量計(jì)算的功能展開(kāi)演示,如下所示,可以看到Dish類(lèi)它記錄了每一個(gè)食物的名稱(chēng)、熱量、類(lèi)型等信息:

public class Dish {

    /**
     * 名稱(chēng)
     */
    private final String name;
    /**
     * 是否是素食
     */
    private final boolean vegetarian;
    /**
     * 卡路里
     */
    private final int calories;
    /**
     * 類(lèi)型
     */
    private final Type type;

    //類(lèi)型枚舉 分別是是:肉類(lèi) 魚(yú)類(lèi) 其他
    public enum Type {MEAT, FISH, OTHER}

    public Dish(String name, boolean vegetarian, int calories, Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    //...... get set


}

基于這個(gè)食物類(lèi),我們給出一個(gè)食物類(lèi)的集合作為模擬數(shù)據(jù):

public static final List<Dish> menuList =
            Arrays.asList(
                    new Dish("pork", false, 800, Dish.Type.MEAT),
                    new Dish("beef", false, 700, Dish.Type.MEAT),
                    new Dish("chicken", false, 400, Dish.Type.MEAT),
                    new Dish("french fries", true, 530, Dish.Type.OTHER),
                    new Dish("rice", true, 350, Dish.Type.OTHER),
                    new Dish("season fruit", true, 120, Dish.Type.OTHER),
                    new Dish("pizza", true, 550, Dish.Type.OTHER),
                    new Dish("prawns", false, 400, Dish.Type.FISH),
                    new Dish("salmon", false, 450, Dish.Type.FISH)
            );

我們希望計(jì)算出這個(gè)菜肴集合的總熱量,我們可能會(huì)這樣寫(xiě):

 public static void main(String[] args) {
        
        int total = menuList.stream()
                //獲取每個(gè)食物的卡路里
                .map(Dish::getCalories)
                //調(diào)用reduce,從0開(kāi)始累加每個(gè)食物的熱量
                .reduce(0, Integer::sum);

        System.out.println(total);
    }

輸出結(jié)果如下:

4300

盡管它盡可能的簡(jiǎn)潔并計(jì)算出了總熱量,但是它存在許多隱患,首先時(shí)map時(shí),它會(huì)將基本類(lèi)型的calories裝箱成Integer,這一點(diǎn)我們查看map的返回值即可知曉。

Stream<Integer> integerStream = menuList.stream()
                //獲取每個(gè)食物的卡路里
                .map(Dish::getCalories);

因?yàn)槟玫降氖前b類(lèi)的流,調(diào)用reduce進(jìn)行數(shù)值計(jì)算時(shí),有需要對(duì)其進(jìn)行拆箱,拆箱時(shí)就會(huì)調(diào)用到IntegerintValue方法:

public int intValue() {
        return value;
    }

所以若在大量數(shù)值計(jì)算的情況下,頻繁的拆箱和裝箱勢(shì)必導(dǎo)致程序的執(zhí)行效率低下。

特值流

那么有沒(méi)有什么辦法可以保證在數(shù)據(jù)收集的時(shí)候避免頻繁裝箱和拆箱呢?答案是特化流,就以本案例來(lái)說(shuō),我們?cè)跀?shù)值收集的時(shí)候直接調(diào)用mapToInt方法,通過(guò)該方法即可得到每一個(gè)數(shù)值的特值流IntStream,隨后我們直接調(diào)用特值流計(jì)算方法sum即可完成熱量統(tǒng)計(jì):

對(duì)應(yīng)的代碼示例如下:

public static void main(String[] args) {
        int total = menuList.stream()
                //將每一個(gè)卡路里轉(zhuǎn)換為特值流IntStream
                .mapToInt(Dish::getCalories)
                //將所有數(shù)值累加
                .sum();

        System.out.println(total);
    }

最終輸出結(jié)果也是4300:

4300

相較于reduce方法,特值流提供了更多更方便的計(jì)算API

  • average:計(jì)算所有數(shù)值的平均數(shù)。
  • count:獲取數(shù)值總數(shù)。
  • max:獲取收集數(shù)據(jù)中的最大值。
  • min:獲取收集數(shù)據(jù)中的最小值。

特化流還原會(huì)原始流

有時(shí)候我們希望這些特化流轉(zhuǎn)為原始流即包裝類(lèi)的流,那么我們可直接調(diào)用boxed方法完成對(duì)特值流的裝箱:

 public static void main(String[] args) {

        
        Stream<Integer> integerStream = menuList.stream()
                //拿到所有數(shù)值的特值流
                .mapToInt(Dish::getCalories)
                //將所有特值流裝箱
                .boxed();

        //輸出特值流對(duì)象的數(shù)值
        integerStream.forEach(i -> System.out.println(i));

    }

特化流空數(shù)值問(wèn)題

我們都知道特化流可以直接獲取收集到數(shù)值的最大值或者最小值,我們假設(shè)這樣一個(gè)場(chǎng)景,食物類(lèi)對(duì)象的卡路里字段為Integer

private final Integer calories;

并且我們食物類(lèi)的集合為空:

 public static final List<Dish> menuList = new ArrayList<>();

面對(duì)可能存在的空結(jié)果問(wèn)題,要如何解決呢?

實(shí)際上java8已經(jīng)考慮到這個(gè)問(wèn)題了,當(dāng)我們調(diào)用max等計(jì)算API獲取結(jié)果時(shí),它實(shí)際返回的對(duì)象是OptionalInt,該對(duì)象提供了各種API用于判斷數(shù)值是否為空,當(dāng)我們最大值為空,就直接返回1時(shí),我們可以直接使用orElse方法:

public static void main(String[] args) {

        OptionalInt max = menuList.stream()
                .mapToInt(Dish::getCalories)
                .max();
        
        //不存在最大值時(shí),直接返回1
        System.out.println(max.orElse(0));


    }

亦或者我們需要判斷是否存在最大值時(shí),可以直接調(diào)用isPresent方法:

public static void main(String[] args) {

        OptionalInt max = menuList.stream()
                .mapToInt(Dish::getCalories)
                .max();

        //若存在最大值直接返回true
        System.out.println(max.isPresent());


    }

數(shù)值流的范圍操作

我們希望統(tǒng)計(jì)1-100之間的偶數(shù)數(shù)量,在java8之前,你可能會(huì)這樣做:

  • for循環(huán)1-100。
  • 判斷是否是偶數(shù)。
  • 如果是偶數(shù),則臨時(shí)變量count自增一下。

java8的步驟則精簡(jiǎn)許多:

  • 基于特值流生成1-100全閉區(qū)間數(shù)據(jù)。
  • 過(guò)濾出偶數(shù)。
  • 調(diào)用count進(jìn)行統(tǒng)計(jì)。
public static void main(String[] args) {
        //生成1-100全閉區(qū)間數(shù)據(jù)
        long count = IntStream.rangeClosed(1, 100)
                //過(guò)濾出偶數(shù)
                .filter(i -> i % 2 == 0)
                //計(jì)算統(tǒng)計(jì)結(jié)果
                .count();

        System.out.println(count);


    }

輸出結(jié)果:

50

當(dāng)然,如果你要生成左閉右開(kāi)即1-99,則可以調(diào)用range方法生成:

IntStream.rangeClosed(1, 99)

數(shù)值流的應(yīng)用——勾股數(shù)

現(xiàn)在我們來(lái)寫(xiě)一個(gè)獲取1-100以?xún)?nèi)前3個(gè)勾股數(shù)的小功能。由公式:

a^2 + b^2=c^2

可知,要想得到勾股數(shù),我們只需判斷a^2 + b^2的和再開(kāi)根號(hào)是否可以被整除,即:

Math.sqrt(a * a + b * b) % 1 == 0

所以我們可以按照下面這樣的步驟執(zhí)行:

  • 創(chuàng)建1-100全閉區(qū)間作為第一條邊a。
  • 為避免計(jì)算的勾股數(shù)重復(fù),出現(xiàn)[3,4,5],[4,3,5]這種情況,我們的第二條邊b范圍為a-100。
  • 拿著a和b,計(jì)算這兩個(gè)數(shù)值的平方和再開(kāi)根號(hào)看看是否為整數(shù)。
  • 將開(kāi)根號(hào)結(jié)果為整數(shù)的結(jié)果生成數(shù)組。
  • 獲取前3個(gè)這樣的數(shù)組。

所以我們寫(xiě)出下面這段代碼,需要注意的是筆者在生成b的時(shí)候用到了flatMap,原因很簡(jiǎn)單,因?yàn)樯蒩時(shí)boxed返回的對(duì)象是Stream<Integer>,假如把這個(gè)流直接用map和b進(jìn)行映射操作的話(huà),最終結(jié)果只能是[Stream<Integer>,Integer,Integer],所以我們需要使用flatMap將a進(jìn)行扁平化從而得到一個(gè)Integer

public static void main(String[] args) {
        //生成a
        Stream<int[]> result = IntStream.rangeClosed(1, 100).boxed()
                //基于a的范圍生成 a-100范圍的b,并過(guò)濾出平方再開(kāi)方后可以整除的b,構(gòu)成數(shù)組
                .flatMap(a -> IntStream.rangeClosed(a, 100).filter(b -> Math.sqrt(a * a + b * b) % 1 == 0).boxed().map(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)}))
                //取前3個(gè)
                .limit(3);

        //打印輸出
        result.forEach(r -> System.out.println(r[0] + " " + r[1] + " " + r[2]));


    }

最終輸出結(jié)果如下:

3 4 5
5 12 13
6 8 10

但是這種寫(xiě)法不夠好,可以看到我們得到合適a和b時(shí),還需要手動(dòng)調(diào)用boxed將其還原為原始流,再用map映射為數(shù)組,這樣實(shí)在太麻煩了。

還記得我們特化流還原為原始流的一個(gè)方法mapToxxx方法嗎?如果我們希望將其轉(zhuǎn)為數(shù)組,我們?cè)诘玫絘和b之后,直接調(diào)用mapToObj,代碼一步到位:

    public static void main(String[] args) {
        //生成a
        Stream<int[]> result = IntStream.rangeClosed(1, 100).boxed()
                //基于a的范圍生成 a-100范圍的b,并過(guò)濾出平方再開(kāi)方后可以整除的b,構(gòu)成數(shù)組
                .flatMap(a -> IntStream.rangeClosed(a, 100).filter(b -> Math.sqrt(a * a + b * b) % 1 == 0).mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)}))
                //取前3個(gè)
                .limit(3);

        //打印輸出
        result.forEach(r -> System.out.println(r[0] + " " + r[1] + " " + r[2]));


    }

以上就是淺聊java8中數(shù)值流的使用的詳細(xì)內(nèi)容,更多關(guān)于java8數(shù)值流的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用kafka如何選擇分區(qū)數(shù)及kafka性能測(cè)試

    使用kafka如何選擇分區(qū)數(shù)及kafka性能測(cè)試

    這篇文章主要介紹了使用kafka如何選擇分區(qū)數(shù)及kafka性能測(cè)試,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java線(xiàn)程中斷及線(xiàn)程中斷的幾種使用場(chǎng)景小結(jié)

    Java線(xiàn)程中斷及線(xiàn)程中斷的幾種使用場(chǎng)景小結(jié)

    在并發(fā)編程中,合理使用線(xiàn)程中斷機(jī)制可以提高程序的魯棒性和可維護(hù)性,本文主要介紹了Java線(xiàn)程中斷及線(xiàn)程中斷的幾種使用場(chǎng)景小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • SpringBoot項(xiàng)目創(chuàng)建單元測(cè)試的流程步驟

    SpringBoot項(xiàng)目創(chuàng)建單元測(cè)試的流程步驟

    在日常開(kāi)發(fā)的過(guò)程中,對(duì)自己的代碼進(jìn)行單元測(cè)試是個(gè)非常重要的過(guò)程,一方面可以最小范圍的針對(duì)一個(gè)方法進(jìn)行測(cè)試,提高測(cè)試的簡(jiǎn)便性以及測(cè)試的成本,本篇文章主要是為了總結(jié)一下如何優(yōu)雅的在Springboot項(xiàng)目中使用單元測(cè)試去測(cè)試功能,需要的朋友可以參考下
    2024-11-11
  • springboot接收excel數(shù)據(jù)文件去重方式

    springboot接收excel數(shù)據(jù)文件去重方式

    文章主要介紹了如何在Spring?Boot中實(shí)現(xiàn)文件上傳并入庫(kù)的功能,包括讀取Excel文件、生成Entity對(duì)象、使用MergeInto語(yǔ)句進(jìn)行數(shù)據(jù)庫(kù)操作以及注意事項(xiàng)
    2024-12-12
  • SpringBoot集成thymeleaf瀏覽器404的解決方案

    SpringBoot集成thymeleaf瀏覽器404的解決方案

    前后端不分離的古早 SpringMVC 項(xiàng)目通常會(huì)使用 thymeleaf 模板引擎來(lái)完成 html 頁(yè)面與后端接口之間的交互,如果要將項(xiàng)目架構(gòu)升級(jí)成 SpringBoot , thymeleaf 也可以照常集成,但有時(shí)候會(huì)踩到一些坑,所以本文給大家介紹了SpringBoot集成thymeleaf瀏覽器404的解決方案
    2024-12-12
  • ElasticSearch學(xué)習(xí)之多條件組合查詢(xún)驗(yàn)證及示例分析

    ElasticSearch學(xué)習(xí)之多條件組合查詢(xún)驗(yàn)證及示例分析

    這篇文章主要為大家介紹了ElasticSearch 多條件組合查詢(xún)驗(yàn)證及示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Java實(shí)現(xiàn)瀏覽器大文件上傳的示例詳解

    Java實(shí)現(xiàn)瀏覽器大文件上傳的示例詳解

    文件上傳是許多項(xiàng)目都有的功能,用戶(hù)上傳小文件速度一般都很快,但如果是大文件幾個(gè)g,幾十個(gè)g的時(shí)候,上傳了半天,馬上就要完成的時(shí)候,網(wǎng)絡(luò)波動(dòng)一下,文件又要重新上傳,所以本文給大家介紹了Java實(shí)現(xiàn)瀏覽器大文件上傳的示例,需要的朋友可以參考下
    2024-07-07
  • Java中scheduleAtFixedRate的用法

    Java中scheduleAtFixedRate的用法

    如何正確使用Java中的scheduleAtFixedRate是一篇介紹Java中定時(shí)任務(wù)調(diào)度器的文章。它詳細(xì)介紹了scheduleAtFixedRate方法的用法、參數(shù)及作用,并給出了一些實(shí)例以幫助讀者更好地理解其使用。本文為Java開(kāi)發(fā)人員提供了一些實(shí)用的技巧,幫助他們更好地管理和控制定時(shí)任務(wù)
    2023-04-04
  • 基于Servlet實(shí)現(xiàn)技術(shù)問(wèn)答網(wǎng)站系統(tǒng)

    基于Servlet實(shí)現(xiàn)技術(shù)問(wèn)答網(wǎng)站系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了基于Servlet實(shí)現(xiàn)技術(shù)問(wèn)答網(wǎng)站系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Java導(dǎo)出Excel文件的方法

    Java導(dǎo)出Excel文件的方法

    項(xiàng)目里很多接口都涉及導(dǎo)出Excel文件,所以本文給大家總結(jié)了項(xiàng)目中導(dǎo)出Excel文件的方法,并通過(guò)代碼示例講解的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2025-02-02

最新評(píng)論