You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按日期参数操作HashMap中对象列表 实现事件间隔校验删除

实现方案

首先先修正你原有代码的两个基础问题:

  • 所有profileID共用同一个全局eventList实例,会导致不同profile的事件完全混存,必须为每个profileID初始化独立的事件列表
  • 事件列表用List<Object>声明会丢失类型信息,后续取事件日期需要强制类型转换,容易抛出类型转换异常,建议定义明确的事件类型(下文统一用Event作为事件类名,包含LocalDateTime eventTime事件时间字段、对应的getter方法)

步骤1:修正数据填充逻辑

原遍历代码里cpToEvent变量未定义,结合你的需求,正确的事件分组填充逻辑如下:

HashMap<String, List<Event>> profileMap = new HashMap<>();
// Plist为你传入的Profile对象列表
for (Profile profile : Plist) {
    String profileId = profile.getprofileID();
    // 不存在当前profile的键时,新建独立的事件列表
    profileMap.putIfAbsent(profileId, new ArrayList<>());
    // 取出当前profile对应的事件列表,添加关联事件
    // 注意替换成你实际获取当前profile对应事件的逻辑
    Event bindEvent = profile.getBindEvent();
    profileMap.get(profileId).add(bindEvent);
}

步骤2:按事件时间对每个profile的事件列表排序

Java 8+直接用List.sort方法结合比较器即可完成排序,不需要自己写排序算法:

// 遍历所有profile的事件列表,按事件时间升序排序(早发生的事件排在前面)
for (List<Event> events : profileMap.values()) {
    events.sort(Comparator.comparing(Event::getEventTime));
}

如果你用的是旧版java.util.Date作为事件时间字段,直接把比较器里的Event::getEventTime换成对应的Date字段getter即可,Date类本身实现了比较接口,可直接排序。

步骤3:遍历排序后的列表,删除间隔超1年的事件

不要在普通正序for循环里直接调用list.remove()删除元素,会触发索引偏移导致漏遍历,推荐用迭代器遍历删除。时间间隔计算优先用java.time.Period,避免手动算毫秒差遇到闰年、夏令时、时区导致的计算误差:

// 定义1年的间隔阈值
private static final int MAX_ALLOWED_YEAR_GAP = 1;

for (List<Event> events : profileMap.values()) {
    // 空列表、只有1个事件的列表不存在相邻间隔,直接跳过
    if (events.size() <= 1) {
        continue;
    }
    Iterator<Event> iterator = events.iterator();
    // 取第一个事件作为初始比对基准
    Event lastValidEvent = iterator.next();
    while (iterator.hasNext()) {
        Event currentEvent = iterator.next();
        // 转换为LocalDate计算年差,忽略时分秒的影响
        LocalDate lastDate = lastValidEvent.getEventTime().toLocalDate();
        LocalDate currentDate = currentEvent.getEventTime().toLocalDate();
        int yearGap = Period.between(lastDate, currentDate).getYears();

        if (yearGap > MAX_ALLOWED_YEAR_GAP) {
            // 间隔超过1年,删除当前事件,保留更早的有效事件作为下一轮基准
            // 如果你需要间隔超1年时同时删除前后两个事件,可以维护一个待删除集合,遍历完成后批量移除
            iterator.remove();
        } else {
            // 间隔符合要求,更新比对基准为当前事件
            lastValidEvent = currentEvent;
        }
    }
}

如果你的事件时间字段是旧的java.util.Date类型,可以用下面的工具方法转成LocalDate再计算间隔:

private static LocalDate dateToLocalDate(Date date) {
    return date.toInstant()
            .atZone(ZoneId.systemDefault())
            .toLocalDate();
}

注意事项

  • 禁止用两个时间的毫秒差除以365*24*60*60*1000的方式计算年间隔,闰年、夏令时切换都会导致计算结果错误
  • 如果你的需求是相邻事件间隔超1年时删除时间更早的事件、或者两个事件都删除,不要在迭代器里连续调用两次remove(),可以先把所有待删除的事件收集到一个Set里,遍历完成后调用events.removeAll(待删除集合),避免遍历状态异常
  • 排序前要确保所有事件的时间字段非空,否则会抛出空指针异常,可以在排序前加过滤逻辑移除时间为空的无效事件

内容的提问来源于stack exchange,提问作者Ujjwal Kuikel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 16:24:53