转载

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

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

版权声明:

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

原文  http://wuwenliang.net/2020/05/17/Java8函数式编程之Stream高阶编程/
正文到此结束
Loading...