当前位置: 首页 > news >正文

苍穹外卖项目日记(day11)

苍穹外卖|项目日记(day11)

​ 前言: 今天的任务不算难, 但如何把代码接口写的像老师那样优雅才是难度.
在这里插入图片描述

今日收获:

1.欣赏了"雅"代码的写法(stram流, 封装查询)

2.加深了对动态sql的使用(group by, order by, limit)

一.stream流的使用

1. Stream的基本概念

Stream(流)代表着一系列元素,支持顺序和并行聚合操作。它不是数据结构,而是从数据源(如集合、数组或I/O资源)获取数据的管道。

主要特点:

  • 不是数据结构:不存储数据,只是从源获取数据
  • 函数式编程:支持lambda表达式和方法引用
  • 惰性执行:中间操作是惰性的,只有终端操作才会触发实际计算
  • 可消费性:流只能被消费一次

创建stream流的方式:

// 从集合创建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream1 = list.stream();// 从数组创建
String[] array = {"a", "b", "c"};
Stream<String> stream2 = Arrays.stream(array);// 直接创建
Stream<String> stream3 = Stream.of("a", "b", "c");// 创建无限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
Stream<Double> randomStream = Stream.generate(Math::random);

3.Stream的操作类型

中间操作(Intermediate Operations)

返回新的Stream,可以链式调用:

.filter(Predicate<T>)   // 过滤
.map(Function<T,R>)     // 转换
.flatMap(Function<T,Stream<R>>) // 扁平化转换
.distinct()             // 去重
.sorted()               // 排序
.limit(long)            // 限制元素数量
.skip(long)             // 跳过前n个元素
终端操作(Terminal Operations)

触发实际计算,返回非Stream结果:

.forEach(Consumer<T>)   // 遍历
.collect(Collector)     // 收集为集合
.toArray()              // 转为数组
.reduce(BinaryOperator<T>) // 归约
.min(Comparator<T>)     // 最小值
.max(Comparator<T>)     // 最大值
.count()                // 计数
.anyMatch(Predicate<T>) // 任意匹配
.allMatch(Predicate<T>) // 全部匹配
.noneMatch(Predicate<T>) // 无匹配
.findFirst()            // 第一个元素
.findAny()              // 任意元素

项目中的使用:

示例:

LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);List<GoodsSalesDTO> salesTop10 = orderMapper.getSalesTop10(beginTime, endTime);List<String> names = salesTop10.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
String nameList = StringUtils.join(names, ",");List<Integer> numbers = salesTop10.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());
String numberList = StringUtils.join(numbers, ",");

对查询条件用map封装:

1. 动态参数传递

使用Map可以灵活地传递不定数量、不定类型的参数。当查询条件可能变化时(比如有时需要添加更多条件),不需要修改方法签名,只需往Map中添加新的键值对即可。

2. 与ORM框架的兼容性

大多数ORM框架(如MyBatis)都支持Map作为参数:

  • MyBatis示例:可以直接在XML映射文件中使用#{beginTime}#{endTime}等表达式引用Map中的值
  • 避免了为每个查询创建专门的参数对象

3. 参数命名清晰

Map的键值对形式使得参数意义明确:

map.put("beginTime", beginTime);  // 比直接传beginTime更明确其用途
map.put("endTime", endTime);
map.put("status", Orders.COMPLETED);

4. 便于参数重用

同一个Map可以在多个查询中复用,或者添加/删除某些参数后用于不同的查询。

5. 简化方法签名

// 相比定义包含多个参数的方法:
Double sumByParams(LocalDateTime begin, LocalDateTime end, OrderStatus status);// 使用Map只需一个参数:
Double sumByMap(Map<String, Object> params)

项目中使用示例:

 // select sum(amount) from orders where order_time > beginTime and order_time < endTime and status = 5Map map = new HashMap();map.put("beginTime", beginTime);map.put("endTime", endTime);map.put("status", Orders.COMPLETED);Double turnover =  orderMapper.sumByMap(map);turnover = turnover == null ? 0.0 : turnover;turnoverList.add(turnover);

二. 销量排名统计的动态sql(Top10)

​ 在最开始, 我不了解如何获取排名前10的菜品, 想法是获取所有订单, 然后遍历获取前10的菜品, 但看了老师的代码后, 才知道对待数据的条件查询, 都可以在sql中实现.

代码示例:

<select id="getSalesTop10" resultType="com.sky.dto.GoodsSalesDTO">select od.name, sum(od.number) as numberfrom order_detail od, orders owhere od.order_id = o.idand o.status = 5  // 指定订单的状态是已完成<if test="begin != null">and o.order_time &gt; #{begin}</if><if test="end != null">and o.order_time &lt; #{end}</if>group by od.name  // 按订单菜品的名字分组order by number desc // 进行降序limit 10 // 获取前10的菜品</select>

不足:

1.对LocalDate与LocalDateTime的认识不足

2.对stram流不熟悉

http://www.lryc.cn/news/590936.html

相关文章:

  • 优先队列的实现
  • vue中的this.$set
  • Spring Cloud LoadBalancer 详解
  • 理解 PS1/PROMPT 及 macOS iTerm2 + zsh 终端配置优化指南
  • javaScript中数组常用的函数方法
  • 【Java开发日记】我们来说说 LockSupport 的 park 和 unpark
  • python Flask 框架入门
  • stack,queue,priority_queue的模拟实现及常用接口
  • 从AWS MySQL数据库下载备份到S3的完整解决方案
  • istio如何自定义重试状态码
  • NLP——迁移学习
  • pytorch学习笔记(五)-- 计算机视觉的迁移学习
  • 浅探C语言的回调函数(Callback Function)
  • 要实现在调用  driver.get()  后立即阻止页面自动跳转到 Azure 登录页,可通过以下几种方法实现:
  • AWS Lambda 最佳实践:构建高效无服务器应用的完整指南
  • Kubernetes ConfigMap 深度指南
  • 大模型Agent应用开发实战:从框架选型到行业落地
  • ros2 标定相机
  • 三轴云台之测距算法篇
  • 《C++初阶之STL》【auto关键字 + 范围for循环 + 迭代器】
  • 【Dv3Admin】菜单管理集成阿里巴巴自定义矢量图标库
  • 大型语言模型(LLM)在网络安全中最具商业价值的应用场景(Grok3 回答 DeepSearch模式)
  • Python包测试全攻略:从单元测试到持续集成
  • sqli-labs靶场通关笔记:第24关 二次注入
  • LiteSQL:让C++与数据库无缝对接的ORM利器
  • 河南萌新联赛2025第一场-河南工业大学
  • Redis面试相关问题总结
  • string + 栈 bitset 可达性统计(拓扑排序)
  • Redis深度解析:从缓存原理到高并发实战
  • Go语言高并发聊天室(三):性能优化与压力测试