Java TreeSet无法去除自定义Lead对象重复项问题求助
问题分析与解决方案
为什么TreeSet没生效?
TreeSet的去重逻辑是当两个对象的compareTo返回0时,才会判定为重复元素,但你的compareTo实现完全不符合需求:
- 你当前的逻辑是先比
_id,再比email,只有当两者都相等时才会比较日期,这意味着:- 两个
_id相同但email不同的Lead,会被TreeSet视为不同元素; - 两个
email相同但_id不同的Lead,也会被视为不同元素;
- 两个
- 更关键的是,你的需求是「
_id相同或email相同即视为重复」,这种“或”的判定逻辑本身就违反了TreeSet依赖的compareTo的传递性要求(比如A和B同_id视为相等,B和C同email视为相等,但A和C既不同_id也不同email,此时A和C应该相等却不相等),所以TreeSet根本不适合处理这种场景。
正确的去重实现
改用HashSet跟踪已出现的_id和email,结合排序保留最新记录,代码示例如下:
// 转换JSON数据到Java对象 LeadsData leads = gson.fromJson(reader, LeadsData.class); // 跟踪已存在的_id和email,避免重复 Set<String> usedIds = new HashSet<>(); Set<String> usedEmails = new HashSet<>(); List<Lead> uniqueLeads = new ArrayList<>(); // 先把所有Lead按entryDate倒序排序,让最新的记录优先被处理 Collections.sort(leads.leads, (leadA, leadB) -> { try { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); Date dateA = dateFormat.parse(leadA.entryDate); Date dateB = dateFormat.parse(leadB.entryDate); // 倒序排序,最新的记录排在前面 return dateB.compareTo(dateA); } catch (ParseException e) { // 日期解析失败时,保持原顺序 return 0; } }); // 遍历筛选去重 for (Lead lead : leads.leads) { // 如果当前lead的_id或email已经存在过,直接跳过 if (usedIds.contains(lead._id) || usedEmails.contains(lead.email)) { continue; } // 否则加入结果集,并标记对应的_id和email为已使用 uniqueLeads.add(lead); usedIds.add(lead._id); usedEmails.add(lead.email); } // 如果需要有序集合,可将uniqueLeads转换为TreeSet或其他有序结构
额外优化建议
- 把
entryDate字段直接定义为Date类型,避免每次解析字符串,提升性能; - 如果
email可能为空,需要在代码里做空值判断,避免空指针异常。
内容的提问来源于stack exchange,提问作者monkeycoder
相关产品推荐
相关产品推荐

