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流式编程的讲解就告一段落,希望本系列对读者朋友们有所帮助。
版权声明:
原创不易,洗文可耻。除非注明,本博文章均为原创,转载请以链接形式标明本文地址。