Java实现指定日期区间的气球对象按日期分组映射的方法咨询
方法实现全流程说明
核心踩坑前置提醒
- 现有代码片段中的
ticketRepository.findTicketByDate命名和实际业务(查询气球)完全不匹配,后续建议同步修正为语义匹配的方法名,降低后续维护的歧义 java.util.Date自带时分秒毫秒精度,直接作为Map键会出现同一个自然日的气球因为时间部分差异被拆分到不同键下的问题,所有参与键计算的日期都必须先做自然日精度对齐- 必须做入参合法性校验:如果
dateStart晚于dateEnd,直接抛出参数校验异常,避免后续日期遍历出现死循环
具体实现步骤
- 入参与日期对齐处理
- 校验
dateStart是否早于等于dateEnd,不满足直接抛出IllegalArgumentException - 把两个入参的时分秒毫秒部分清零,对齐到当日00:00:00的自然日标准,避免区间遍历因为时间偏差漏算首尾日期
- 校验
- 构建临时分组映射
- 遍历已查询到的气球列表,把每个Ballon的
dateCreation字段同样对齐到自然日精度 - 用临时Map存储分组结果:键是对齐后的自然日Date对象,值是对应日期下的Ballon集合
- 遍历已查询到的气球列表,把每个Ballon的
- 逐天填充结果Map
- 按照日期区间的总天数初始化结果Map的容量,避免动态扩容带来的性能损耗
- 从对齐后的
dateStart开始,逐天累加遍历直到覆盖到dateEnd:- 从临时分组Map中取出当前遍历日期对应的气球集合
- 存在对应集合就转成
Ballon[]类型放入结果Map - 不存在对应集合就放入长度为0的空
Ballon[] - 日期累加时以天为单位递增,避免时区问题导致的日期偏移
- 返回填充完成的结果Map
可落地参考代码
public Map<Date, Ballon[]> getMapOfBallonByDate(Date dateStart, Date dateEnd) { // 入参合法性校验 if (dateStart.after(dateEnd)) { throw new IllegalArgumentException("日期区间非法:起始日期不能晚于结束日期"); } // 统一日期精度到自然日 SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd"); Date alignedStart = dayFormat.parse(dayFormat.format(dateStart)); Date alignedEnd = dayFormat.parse(dayFormat.format(dateEnd)); // 查询区间内气球列表(修正原代码的repository语义错误) List<Ballon> allBallonInTheDateInterval = ballonRepository.findBallonByDateBetween(alignedStart, alignedEnd); // 临时分组:按自然日归拢气球 Map<Date, List<Ballon>> tempGroupMap = new HashMap<>(); for (Ballon ballon : allBallonInTheDateInterval) { Date createDay = dayFormat.parse(dayFormat.format(ballon.getDateCreation())); tempGroupMap.computeIfAbsent(createDay, k -> new ArrayList<>()).add(ballon); } // 按区间天数初始化Map容量 long totalDays = (alignedEnd.getTime() - alignedStart.getTime()) / (1000 * 60 * 60 * 24); Map<Date, Ballon[]> resultMap = new HashMap<>((int) (totalDays + 1)); // 逐天填充结果 Calendar calendar = Calendar.getInstance(); calendar.setTime(alignedStart); while (!calendar.getTime().after(alignedEnd)) { Date currentDay = calendar.getTime(); List<Ballon> dayBallons = tempGroupMap.getOrDefault(currentDay, Collections.emptyList()); resultMap.put(currentDay, dayBallons.toArray(new Ballon[0])); // 日期往后推1天 calendar.add(Calendar.DAY_OF_MONTH, 1); } return resultMap; }
边界场景覆盖说明
- 跨月、跨年的日期区间,逐天遍历逻辑不需要额外调整
- 区间内无任何匹配气球时,所有日期对应的value都是空数组,完全符合需求
- 注意时区一致性:日期对齐、Calendar 初始化的时区要和系统存储业务数据的时区保持统一,避免出现日期偏移1天的隐性问题
内容的提问来源于stack exchange,提问作者KuRuVI
相关产品推荐
相关产品推荐

