25

Java8函数式编程之Lambda与传统方式对集合操作的案例对比

 3 years ago
source link: http://wuwenliang.net/2020/05/16/Java8函数式编程之Lambda与传统方式对集合操作的案例对比/
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.

本章节中,我们通过一个实战案例对比原始集合操作与Stream集合操作具体有哪些不同,直观地展示Stream集合操作对编程效率的提升。

案例:对比原始集合操作与Stream集合操作

需求场景:

针对上面的购物车,我们想要

  1. 全局查看购物车中都有哪些商品
  2. 将购物车中的图书类商品进行过滤(删除图书类商品)
  3. 在其余商品中挑选两件最贵的
  4. 打印出上述两件商品的名称和总价

原始集合操作:

@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编程,对于提升我们的编码效率以及提升代码可读性都有着明显的收益。

版权声明:

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK