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

Java移除同ID同状态重复Event对象 保留最大startTime记录报错

问题根因

你的代码存在几类核心问题,直接导致运行异常、返回空列表:

  • 集合操作违规:for-each语法遍历List时直接调用remove()修改集合结构,会触发ConcurrentModificationException;双重循环边遍历边删除会导致索引错位,遍历逻辑混乱,最终误删所有元素得到空列表。
  • 低级拼写/语法错误:
    • 类名错误:Arraylist应为ArrayList,Events应为Event
    • 方法名错误:getid()应为getId(),euqals()应为equals(),getStarttime()应为getStartTime()
    • 字符串比较错误:用==比较Status内容,==比较的是对象内存地址不是字符串值,永远得不到正确匹配
    • 日期格式错误:格式串里yyyy-mm-dd的mm代表分钟,月份必须用大写MM,否则解析时间完全错误
    • 变量名错误:定义的列表叫results,删除时写的result.remove(e)变量不存在
    • 状态值大小写不匹配:判断的状态是"InProgress"(P大写),实际数据里是"Inprogress"(p小写),判断条件根本不会生效
  • 去重逻辑缺陷:双重循环两两比较时,只要当前元素e比遍历到的e1时间早就删e,没有做分组保留最大时间的判断,哪怕是符合保留要求的最大时间元素,遍历到比它小的元素时也可能被误判删除。
正确实现

不要使用边遍历边删除的逻辑,直接按「ID+状态」做分组,每个分组只保留startTime最大的记录即可,逻辑清晰不会触发并发修改问题,也适配列表动态更新的场景。

Java 8+ 简洁实现(推荐)

用Stream的toMap做分组聚合,代码简洁易维护:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

public List<Event> removeDuplicates(List<Event> source) {
    // 注意日期格式:月份必须用大写MM
    DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
    return new ArrayList<>(source.stream()
            // 过滤空对象、空ID的无效数据
            .filter(Objects::nonNull)
            .filter(event -> event.getId() != null && !event.getId().isBlank())
            // 按需打开下方注释,只保留Inprogress状态的记录
            // .filter(event -> "Inprogress".equals(event.getStatus()))
            // 按ID+状态做分组,同组只保留时间最大的记录
            .collect(Collectors.toMap(
                    // 分组key:同ID同状态判定为同一组
                    event -> event.getId() + "_" + event.getStatus(),
                    event -> event,
                    // 同组两条记录冲突时,选择startTime更晚的记录保留
                    (oldVal, newVal) -> {
                        LocalDateTime oldTime = LocalDateTime.parse(oldVal.getStartTime(), timeFormatter);
                        LocalDateTime newTime = LocalDateTime.parse(newVal.getStartTime(), timeFormatter);
                        return oldTime.isAfter(newTime) ? oldVal : newVal;
                    }
            ))
            .values());
}

低版本Java兼容实现

不支持Stream的环境可以用HashMap临时存储分组结果,逻辑和上述实现一致:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public List<Event> removeDuplicates(List<Event> source) {
    DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    Map<String, Event> groupContainer = new HashMap<>();
    
    for (Event event : source) {
        if (event == null || event.getId() == null || event.getId().isBlank()) {
            continue;
        }
        // 按需打开下方注释,只保留Inprogress状态的记录
        // if (!"Inprogress".equals(event.getStatus())) continue;
        
        String groupKey = event.getId() + "_" + event.getStatus();
        Event existedEvent = groupContainer.get(groupKey);
        if (existedEvent == null) {
            groupContainer.put(groupKey, event);
            continue;
        }
        // 比较时间,将分组内记录替换为时间更晚的条目
        LocalDateTime existedTime = LocalDateTime.parse(existedEvent.getStartTime(), timeFormatter);
        LocalDateTime currentTime = LocalDateTime.parse(event.getStartTime(), timeFormatter);
        if (currentTime.isAfter(existedTime)) {
            groupContainer.put(groupKey, event);
        }
    }
    return new ArrayList<>(groupContainer.values());
}
避坑提醒
  • 所有字符串值比较必须用equals(),绝对不要用==
  • 日期格式符严格区分大小写,使用前对照DateTimeFormatter规则确认符号含义
  • for-each遍历集合时禁止直接调用add/remove修改集合结构,必须遍历删除请使用Iterator的remove()方法
  • 去重、分组类逻辑优先用中间容器暂存结果,不要在原列表上反复遍历删除,逻辑混乱极易出bug

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:06:20