欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

簡介

java8為我提供的簡單快捷的數(shù)值流計算API,本文就基于幾個常見的場景介紹一下數(shù)值流API的使用。

基礎(chǔ)示例

我們以一個食物熱量計算的功能展開演示,如下所示,可以看到Dish類它記錄了每一個食物的名稱、熱量、類型等信息:

public class Dish {

    /**
     * 名稱
     */
    private final String name;
    /**
     * 是否是素食
     */
    private final boolean vegetarian;
    /**
     * 卡路里
     */
    private final int calories;
    /**
     * 類型
     */
    private final Type type;

    //類型枚舉 分別是是:肉類 魚類 其他
    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


}

基于這個食物類,我們給出一個食物類的集合作為模擬數(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)
            );

我們希望計算出這個菜肴集合的總熱量,我們可能會這樣寫:

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

        System.out.println(total);
    }

輸出結(jié)果如下:

4300

盡管它盡可能的簡潔并計算出了總熱量,但是它存在許多隱患,首先時map時,它會將基本類型的calories裝箱成Integer,這一點我們查看map的返回值即可知曉。

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

因為拿到的是包裝類的流,調(diào)用reduce進行數(shù)值計算時,有需要對其進行拆箱,拆箱時就會調(diào)用到IntegerintValue方法:

public int intValue() {
        return value;
    }

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

特值流

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

對應的代碼示例如下:

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

        System.out.println(total);
    }

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

4300

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

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

特化流還原會原始流

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

 public static void main(String[] args) {

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

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

    }

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

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

private final Integer calories;

并且我們食物類的集合為空:

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

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

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

public static void main(String[] args) {

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


    }

亦或者我們需要判斷是否存在最大值時,可以直接調(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)計1-100之間的偶數(shù)數(shù)量,在java8之前,你可能會這樣做:

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

java8的步驟則精簡許多:

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

        System.out.println(count);


    }

輸出結(jié)果:

50

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

IntStream.rangeClosed(1, 99)

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

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

a^2 + b^2=c^2

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

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

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

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

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

public static void main(String[] args) {
        //生成a
        Stream<int[]> result = IntStream.rangeClosed(1, 100).boxed()
                //基于a的范圍生成 a-100范圍的b,并過濾出平方再開方后可以整除的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個
                .limit(3);

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


    }

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

3 4 5
5 12 13
6 8 10

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

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

    public static void main(String[] args) {
        //生成a
        Stream<int[]> result = IntStream.rangeClosed(1, 100).boxed()
                //基于a的范圍生成 a-100范圍的b,并過濾出平方再開方后可以整除的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個
                .limit(3);

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


    }

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

相關(guān)文章

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

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

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

    Java線程中斷及線程中斷的幾種使用場景小結(jié)

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

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

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

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

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

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

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

    ElasticSearch學習之多條件組合查詢驗證及示例分析

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

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

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

    Java中scheduleAtFixedRate的用法

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

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

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

    Java導出Excel文件的方法

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

最新評論