实战:集合与流操作对比
分别使用集合操作及Stream流操作,完成对实际应用场景中的数据处理。直观感受流操作带来的便捷性。
购物车案例
沿用Java之函数编程中的购物车的案例。
需求条件:
- 想看看购物车中都有什么商品
- 图书类商品都给买
- 其余的商品中买两件最贵的
- 只需要两件商品的名称和总价
传统方式处理业务逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
public static void oldCartHandle() { List<Sku> cartSKuList = CartService.getCartSKuList(); for (Sku sku : cartSKuList) { System.out.println(JSONUtil.parse(sku)); } List<Sku> notBooksSkuList = new ArrayList<>(); for (Sku sku : cartSKuList) { if (!SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory())) { notBooksSkuList.add(sku); } } notBooksSkuList.sort(new Comparator<Sku>() { @Override public int compare(Sku sku1, Sku sku2) { if (sku1.getTotalPrice() > sku2.getTotalPrice()) { return -1; } else if (sku1.getTotalPrice() < sku2.getTotalPrice()) { return 1; } else { return 0; } } }); List<Sku> topTwoSkuList = new ArrayList<>(); for (int i = 0; i < 2; i++) { topTwoSkuList.add(notBooksSkuList.get(i)); } Double money = 0.00; for (Sku sku : topTwoSkuList) { money += sku.getTotalPrice(); } List<String> resultSkuNameList = new ArrayList<>(); for (Sku sku : topTwoSkuList) { resultSkuNameList.add(sku.getSkuName()); } System.out.println(JSONUtil.parse(resultSkuNameList)); System.out.println("商品总价:" + money); }
|
Lambda与Stream处理业务逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
public static void newCartHandle() { AtomicReference<Double> money = new AtomicReference<>(0.0); List<String> resultSkuNameList = CartService.getCartSKuList() .stream() .peek(sku -> System.out.println(JSONUtil.parse(sku))) .filter(sku -> !SkuCategoryEnum.BOOKS.equals(sku.getSkuCategory())) .sorted(Comparator.comparing(Sku::getTotalPrice).reversed()) .limit(2) .peek(sku -> money.set(money.get() + sku.getTotalPrice())) .map(Sku::getSkuName) .collect(Collectors.toList()); System.out.println(JSONUtil.parse(resultSkuNameList)); System.out.println("商品总价:" + money.get()); }
|
Stream流
流是什么?
- JDK1.8引入的新成员,以声明式方式处理集合数据
- 将基础操作链接起来,完成复杂的数据处理流水线
- 提供透明的并行处理
流的简介
从支持数据处理操作的源生成的元素序列。 – Java8实战
- 元素序列:在java.util.stream.Stream当中定义了一个新的接口,可以访问特定元素类型的一组有序值。当中有stream方法,可以返回一个流。流的目的在于表达计算
- 源:流会使用一个包含数据的源,比如集合,数组,输入输出的资源等。从有序集合生成流时会保留原有的顺序。由列表生成的流,其元素顺序与列表一致。
- 数据处理的操作:流的数据处理功能支持类似于数据库的操作,以及函数式编程语言中 的常用操作。流可以顺序执行,也可以并行执行。并行执行用parallStream就行。数据处理的操作就是 一个中间操作链,形成一条流的流水线。这些操作会返回一个流,但是如果没有终端操作,这些操作并不会执行。
流与集合的区别
- 时间(流)与空间(集合)
- 只能遍历一次
- 外部迭代与内部迭代
流的组成

流操作分类

流的使用

- 短路:执行时遇到满足条件则直接返回,不会继续执行
- 非短路:执行时遇到满足条件则不会直接返回,会继续执行完成
- 有状态:有状态就是有数据存储功能,线程不安全
- 无状态:无状态就是一次操作,不能保存数据,线程安全