本文是Java8函数式编程的最后一个章节,到此我们的Stream相关的讲解就暂时告一段落。
本文中我将带领读者朋友一起学习一下Stream高级编程相关的知识。
Stream操作中有两个相对高阶的概念,分别为规约和汇总。
规约(reduce)
将Stream流中元素转换成一个值
汇总(collect)
将Stream流中的元素转换成一个容器,如Map 、List 、 Set
上文我们已经讲过了汇总操作Collect,此处我们重点讲讲规约操作(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
通过上述的介绍,我们能够总结出Stream的特点:
无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
由于篇幅及笔者个人能力有限,不能将Java8的所有特性都详细的呈现,感兴趣的同学可以自行学习。
Optional 接口默认方法 新的日期和时间API CompletableFuture:组合式异步编程 G1垃圾回收器
推荐阅读
《Java8实战》Java8 In Action中文版 《深入理解JVM&G1 GC》
到此,针对Java8的新特性Lambda表达式及stream流式编程的讲解就告一段落,希望本系列对读者朋友们有所帮助。
版权声明:
原创不易,洗文可耻。除非注明,本博文章均为原创,转载请以链接形式标明本文地址。