40

Java8函数式编程之Stream高阶编程

 3 years ago
source link: http://wuwenliang.net/2020/05/17/Java8函数式编程之Stream高阶编程/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文是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流式编程的讲解就告一段落,希望本系列对读者朋友们有所帮助。

版权声明:

原创不易,洗文可耻。除非注明,本博文章均为原创,转载请以链接形式标明本文地址。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK