Java8函数式编程之Lambda与传统方式对集合操作的案例对比
本章节中,我们通过一个实战案例对比原始集合操作与Stream集合操作具体有哪些不同,直观地展示Stream集合操作对编程效率的提升。
案例:对比原始集合操作与Stream集合操作
需求场景:
针对上面的购物车,我们想要
- 全局查看购物车中都有哪些商品
- 将购物车中的图书类商品进行过滤(删除图书类商品)
- 在其余商品中挑选两件最贵的
- 打印出上述两件商品的名称和总价
原始集合操作:
@Test
public void traditionalWay() {
// 1. 打印所有商品
List<Sku> skus = CartService.getCartSkuList();
for (Sku sku : skus) {
System.out.println(JSON.toJSONString(sku, true));
}
// 2. 过滤图书类商品
List<Sku> notIncludeBooksList = new ArrayList<>();
for (Sku sku : skus) {
if (!sku.getSkuCategory().equals(SkuCategoryEnum.BOOKS)) {
notIncludeBooksList.add(sku);
}
}
// 3. 其余商品中挑选两件最贵的 价格倒排序,取top2
// 3.1 先排序
notIncludeBooksList.sort(new Comparator<Sku>() {
@Override
public int compare(Sku sku0, Sku sku1) {
if (sku0.getTotalPrice() > sku1.getTotalPrice()) {
return -1;
}
if (sku0.getTotalPrice() < sku1.getTotalPrice()) {
return 1;
}
return 0;
}
});
// 3.2 取top2
List<Sku> top2SkuList = new ArrayList<>();
for (int i = 0; i < 2; i++) {
top2SkuList.add(notIncludeBooksList.get(i));
}
// 4. 打印出上述两件商品的名称和总价
// 4.1 求两件商品总价
double totalMoney = 0.0;
for (Sku sku : top2SkuList) {
totalMoney += sku.getTotalPrice();
}
// 4.2 获取两件商品名称
List<String> resultSkuNameList = new ArrayList<>();
for (Sku sku : top2SkuList) {
resultSkuNameList.add(sku.getSkuName());
}
// 打印输出结果
System.out.println("结果商品名称: " + JSON.toJSONString(resultSkuNameList, true));
System.out.println("商品总价:" + totalMoney);
}
运行结果:
{"skuCategory":"ELECTRONICS","skuId":2,"skuName":"无人机","skuPrice":1000.0,"totalNum":10,"totalPrice":1000.0}
{"skuCategory":"ELECTRONICS","skuId":1,"skuName":"VR一体机","skuPrice":2100.0,"totalNum":10,"totalPrice":2100.0}
{"skuCategory":"CLOTHING","skuId":4,"skuName":"牛仔裤","skuPrice":60.0,"totalNum":10,"totalPrice":60.0}
{"skuCategory":"CLOTHING","skuId":13,"skuName":"衬衫","skuPrice":120.0,"totalNum":10,"totalPrice":120.0}
{"skuCategory":"BOOKS","skuId":121,"skuName":"Java编程思想","skuPrice":100.0,"totalNum":10,"totalPrice":100.0}
{"skuCategory":"BOOKS","skuId":3,"skuName":"程序化广告","skuPrice":80.0,"totalNum":10,"totalPrice":80.0}
结果商品名称: [
"VR一体机",
"无人机"
]
商品总价:3100.0
我们可以看到传统的集合操作还是写了比较多的代码,而且在编码过程中为了满足各种要求,我们通过声明新的容器来接受过程中的操作结果,这带来了内存使用量的增加。
接下来看一下Stream方式下如何编码实现我们的需求:
Stream集合操作:
@Test
public void streamWay() {
AtomicReference<Double> money = new AtomicReference<>(Double.valueOf(0.0));
List<String> resultSkuNameList = CartService.getCartSkuList()
// 获取集合流
.stream()
/**1. 打印商品信息*/
.peek(sku -> System.out.println(JSON.toJSONString(sku)))
/**2. 过滤掉所有的图书类商品*/
.filter(sku -> !SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory()))
/**3. 价格进行排序,默认是从小到大,调用reversed进行翻转排序即从大到小*/
.sorted(Comparator.comparing(Sku::getTotalPrice).reversed())
/**4. 取top2*/
.limit(2)
/**累加金额*/
.peek(sku -> money.set(money.get() + sku.getTotalPrice()))
/**获取商品名称*/
.map(sku -> sku.getSkuName())
.collect(Collectors.toList());
System.out.println("商品总价:" + money.get());
System.out.println("商品名列表:" + JSON.toJSONString(resultSkuNameList));
}
运行结果:
{"skuCategory":"ELECTRONICS","skuId":2,"skuName":"无人机","skuPrice":1000.0,"totalNum":10,"totalPrice":1000.0}
{"skuCategory":"ELECTRONICS","skuId":1,"skuName":"VR一体机","skuPrice":2100.0,"totalNum":10,"totalPrice":2100.0}
{"skuCategory":"CLOTHING","skuId":4,"skuName":"牛仔裤","skuPrice":60.0,"totalNum":10,"totalPrice":60.0}
{"skuCategory":"CLOTHING","skuId":13,"skuName":"衬衫","skuPrice":120.0,"totalNum":10,"totalPrice":120.0}
{"skuCategory":"BOOKS","skuId":121,"skuName":"Java编程思想","skuPrice":100.0,"totalNum":10,"totalPrice":100.0}
{"skuCategory":"BOOKS","skuId":3,"skuName":"程序化广告","skuPrice":80.0,"totalNum":10,"totalPrice":80.0}
商品总价:3100.0
商品名列表:["VR一体机","无人机"]
我们可以看到,通过Stream集合操作,运行结果与传统集合操作完全一致。但是编码量却能够显著减少。
辩证的分析一下,如果对Stream操作没有一个较为明确的了解,阅读这段代码确实有些难度,但是只要有一点了解,Stream集合操作代码带来的无论是编码量显著降低还是可读性提升,亦或是内存空间的节约都是可观的。
阶段小结
可见,学习并运用Lambda及Stream编程,对于提升我们的编码效率以及提升代码可读性都有着明显的收益。
版权声明:
原创不易,洗文可耻。除非注明,本博文章均为原创,转载请以链接形式标明本文地址。