一、使用StreamAPI,(基于数据模型——客户、订单和商品,实体关系图如下,客户可以有多个订单,是一对多的关系,而产品和订单的关系是多对多的)需求如下:
二、Stream API思维导图
三、需求:
练习 1 — 获取商品属于"励志"类别的订单信息
练习 2 — 获取商品"小说"类别的价格最贵的。
练习 3 — 获取类别是"小说"的商品,且价格为8折销售。
练习 4 — 获取类别是"小说"的商品,且价格>95的商品信息。
练习 5 — 获取最近的 2 个订单
练习 6 — 计算 2024 年 1 月的所有订单的总金额
练习 7 — 获取"小说"的所有商品的聚合数据(即总和、平均值、最个数大值、最小值、个数)
练习 8 — 获取订单中的ID和订单产品数量的数据
练习 9 — 生成按客户分组的订单记录的数据映射
练习 10 - 获取每个订单商品总价
四、编码
4.1 、原始数据
List<Order> orders = null;List<Product> products = null;List<Customer> customers = null;@Beforepublic void load() {Product p1 = new Product(1, "人性的弱点", "励志", 56.89);Product p2 = new Product(2, "爱丽丝漫游奇境", "科幻", 26.60);Product p3 = new Product(3, "三国演义", "小说", 85.00);Product p4 = new Product(4, "水浒传", "小说", 99.00);Product p5 = new Product(5, "西游记", "小说", 95.00);Product p6 = new Product(6, "红楼梦", "小说", 105.00);//商品集合products = Arrays.asList(p1, p2, p3, p4, p5, p6);Customer c1 = new Customer(1, "刘芳", 1);Customer c2 = new Customer(2, "单满", 2);Customer c3 = new Customer(3, "王莉", 3);Customer c4 = new Customer(4, "程海燕", 1);Customer c5 = new Customer(5, "王城", 2);Customer c6 = new Customer(6, "王和明", 3);//客户集合customers = Arrays.asList(c1, c2, c3, c4, c5, c6);//集合数据List<Product> products1 = Arrays.asList(p1, p2, p3,p4);List<Product> products2 = Arrays.asList(p1, p4, p5);List<Product> products3 = Arrays.asList(p3, p2, p4);List<Product> products4 = Arrays.asList(p1, p5, p6);Order o1 = new Order(10010, "1", LocalDate.of(2024, 1, 3), LocalDate.of(2024, 1, 25), products1, c1);Order o2 = new Order(10011, "1", LocalDate.of(2024, 2, 5), LocalDate.of(2024, 2, 26), products2, c2);Order o3 = new Order(10012, "2", LocalDate.of(2024, 1, 8), LocalDate.of(2024, 1, 30), products3, c3);Order o4 = new Order(10013, "2", LocalDate.of(2024, 3, 1), LocalDate.of(2024, 3, 18), products4, c3);//订单集合orders = Arrays.asList(o1, o2, o3, o4);
// System.out.println(orders);}
4.2、 操作1-10小题
// 练习 1 — 获取商品属于"励志"类别的订单信息@Testpublic void test1() {List<Order> list = orders.stream().filter(o -> o.getProducts().stream().anyMatch(p -> p.getKind().equals("励志"))).collect(Collectors.toList());System.out.println(list);}// 练习 2 — 获取商品"小说"类别的价格最贵的。@Testpublic void test2() {Optional<Product> ll = products.stream().filter(p -> p.getKind().equals("小说")).max(Comparator.comparing(Product::getPrice));System.out.println(ll.get());}// 练习 3 — 获取类别是"小说"的商品,且价格为8折销售。@Testpublic void test3() {List<Double> ll = products.stream().filter(p -> p.getKind().equals("小说")).map(p -> p.getPrice() * 0.8).collect(Collectors.toList());System.out.println(ll);}// 练习 4 — 获取类别是"小说"的商品,且价格>95的商品信息。@Testpublic void test4() {products.stream().filter(p -> p.getKind().equals("小说")).filter(p -> p.getPrice() > 95).forEach(System.out::println);}// 练习 5 — 获取最近的 2 个订单@Testpublic void test5() {orders.stream().sorted(Comparator.comparing(Order::getOrderDate).reversed()) //降序.limit(2).forEach(System.out::println);}// 练习 6 — 计算 2024 年 1 月的所有订单的总金额@Testpublic void test6() {double sums= orders.stream().filter(o->o.getOrderDate().compareTo(LocalDate.of(2024,1,1))>=0).filter(o->o.getOrderDate().compareTo(LocalDate.of(2024,2,1))<=0).flatMap(p->p.getProducts().stream()).mapToDouble(Product::getPrice).sum();System.out.println(sums);}// 练习 7 — 获取类别"小说"的所有商品的统计数据(即总和、平均值、最大值、最小值、个数)@Testpublic void test7() {DoubleSummaryStatistics dss= products.stream().filter(p -> p.getKind().equals("小说")).mapToDouble(Product::getPrice).summaryStatistics();System.out.println(dss);}// 练习 8 — 获取订单中的ID和订单产品数量的数据@Testpublic void test8() {Map<Long,Integer> map= orders.stream().collect(Collectors.toMap(Order::getOid,o->o.getProducts().size()));System.out.println(map);}// 练习 9 — 生成按客户分组的订单记录的数据映射@Testpublic void test9() {Map<Customer,List<Order>> map= orders.stream().collect(Collectors.groupingBy(Order::getCustomer));System.out.println(map);}// 练习 10 - 获取每个订单商品总价@Testpublic void test10() {Map<Order,Double> map= orders.stream().collect(Collectors.toMap(Function.identity(),o->o.getProducts().stream().mapToDouble(Product::getPrice).sum()));System.out.println(map);}
五、总结:
采用 Java Stream API 是一种思维转变,从传统的命令式编程转变为函数式编程。因此,练习帮助我们思考流数据流中的逻辑很重要。