本文是Java8函數式編程的最後一個章節,到此我們的Stream相關的講解就暫時告一段落。

本文中我將帶領讀者朋友一起學習一下Stream高級編程相關的知識。

規約與彙總

Stream操作中有兩個相對高階的概念,分別爲規約和彙總。

規約(reduce)

將Stream流中元素轉換成一個值

彙總(collect)

將Stream流中的元素轉換成一個容器,如Map 、List 、 Set

上文我們已經講過了彙總操作Collect,此處我們重點講講規約操作(reduce)

對reduce的理解

reduce 操作可以實現從Stream中生成一個值,其生成的值不是隨意的,是根據指定的計算模型。

比如,之前提到count、min和max方法,因爲常用而被納入標準庫中。事實上,這些方法都是reduce操作。

我們看一個案例

/**
    * reduce 案例1:
    *      計算一批商品的總價格
    */
    @Test
    public void reduceTest() {

        /**
        * 準備一批訂單數據
        */
        List<Order> list = Lists.newArrayList();
        list.add(new Order(1, 2, 15.12));
        list.add(new Order(2, 5, 257.23));
        list.add(new Order(3, 3, 23331.12));

        /**
        * 傳統方式
        * 1. 計算商品數量
        * 2. 計算消費總金額
        *
        * 以下展示Stream的reduce方式
        * 思想:分治法
        *
        *     <U> U reduce(U identity,                                 初始基點,此處就是訂單中屬性都是0
        *                  BiFunction<U, ? super T, U> accumulator,    計算邏輯,定義兩個元素如何進行操作
        *                  BinaryOperator<U> combiner);                並行執行時多個部分結果的合併方式
        *
        */

        /**
        * 彙總商品數量和總金額
        */
        Order order = list.stream()
                //.parallel()     // 並行方式
                .reduce(
                        // 參數1:初始化值
                        new Order(0, 0, 0.0),
                        // 參數2:Stream中兩個元素的計算邏輯
                        (Order order1, Order order2) -> {
                            System.out.println("執行 計算邏輯 方法!!!");
                            // 計算兩個訂單商品數量和,消費金額之和
                            int productCount = order1.getProductCount() + order2.getProductCount();
                            double totalAmount = order1.getTotalAmount() + order2.getTotalAmount();
                            // 返回計算結果
                            return new Order(0, productCount, totalAmount);
                        },
                        // 參數3:並行情況下,多個並行結果如何合併
                        (Order order1, Order order2) -> {
                            System.out.println("執行 合併 方法!!!");
                            // 計算兩個訂單商品數量和,消費金額之和
                            int productCount = order1.getProductCount() + order2.getProductCount();
                            double totalAmount = order1.getTotalAmount() + order2.getTotalAmount();
                            // 返回計算結果
                            return new Order(0, productCount, totalAmount);
                        });
        System.out.println(JSON.toJSONString(order, true));
    }
}

運行結果:

執行 計算邏輯 方法!!!
執行 計算邏輯 方法!!!
執行 計算邏輯 方法!!!
{
    "id":0,
    "productCount":10,
    "totalAmount":23603.469999999998
}

可見通過reduce邏輯,我們能夠很輕鬆實現注入複雜條件的累加,求最值等操作。

reduce規約操作,實際上採用了分治思想,提升了編碼和執行效率。

更多關於reduce的解析可以參考 https://blog.csdn.net/weixin_41835612/article/details/83687078

4.9 Stream特點:

通過上述的介紹,我們能夠總結出Stream的特點:

  • 無存儲。stream不是一種數據結構,它只是某種數據源的一個視圖,數據源可以是一個數組,Java容器或I/O channel等。

  • 爲函數式編程而生。對stream的任何修改都不會修改背後的數據源,比如對stream執行過濾操作並不會刪除被過濾的元素,而是會產生一個不包含被過濾元素的新stream。

  • 惰式執行。stream上的操作並不會立即執行,只有等到用戶真正需要結果的時候纔會執行。

  • 可消費性。stream只能被“消費”一次,一旦遍歷過就會失效,就像容器的迭代器那樣,想要再次遍歷必須重新生成。

更多Java8特性

由於篇幅及筆者個人能力有限,不能將Java8的所有特性都詳細的呈現,感興趣的同學可以自行學習。

Optional

接口默認方法

新的日期和時間API

CompletableFuture:組合式異步編程

G1垃圾回收器

推薦閱讀

《Java8實戰》Java8 In Action中文版

《深入理解JVM&G1 GC》

總結

到此,針對Java8的新特性Lambda表達式及stream流式編程的講解就告一段落,希望本系列對讀者朋友們有所幫助。

版權聲明:

原創不易,洗文可恥。除非註明,本博文章均爲原創,轉載請以鏈接形式標明本文地址。

相關文章