基于邮箱与手机号去重的客户列表合并:求更简便实现方案
客户列表去重合并的简便实现方式
我在数据库中存储了一份客户列表,需要实现该列表的更新功能并进行重复项校验。客户重复判定规则为对比邮箱与手机号,即仅添加邮箱和手机号均未在库中的客户,完成新旧列表合并。请问是否有更简便的实现方式?
现有实现代码
public class DateTest { public static void main(String[] args) { TestObject t1 = new TestObject(1, "+111", "email1", "Ivan"); TestObject t2 = new TestObject(2, "+222", "email2", "Ilya"); TestObject t3 = new TestObject(3, "+333", "email3", "Pavel"); TestObject t4 = new TestObject(null, "+444", "email4", "Anna"); TestObject t5 = new TestObject(null, "+111", "email1", "Ivan"); TestObject t6 = new TestObject(null, "+222", "email2", "Ivan"); List<TestObject> testObjects = Arrays.asList(t1, t2, t3); List<TestObject> newTestObjects = Arrays.asList(t4, t5, t6); List<TestObject> notPresentObj = newTestObjects.stream().filter(client -> !testObjects.contains(client)).collect(Collectors.toList()); List<TestObject> newList = Stream.concat(testObjects.stream(),notPresentObj.stream()).collect(Collectors.toList()); System.out.println(newList); } } class TestObject { private Integer id; private String phoneNubmer; private String email; private String name; public TestObject(Integer id, String phoneNubmer, String email, String name) { this.id = id; this.phoneNubmer = phoneNubmer; this.email = email; this.name = name; } //getters, setters and toString @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TestObject that = (TestObject) o; return Objects.equals(phoneNubmer, that.phoneNubmer) && Objects.equals(email, that.email); } @Override public int hashCode() { return Objects.hash(phoneNubmer, email); } }
优化方案
1. 内存层面:提升去重校验性能
原代码中List.contains()的时间复杂度是O(n),当客户数量较多时效率低下。可以将现有客户列表转换为HashSet,利用其O(1)的查询效率:
// 将现有客户存入HashSet,快速判断重复 Set<TestObject> existingClients = new HashSet<>(testObjects); // 筛选出新列表中不存在的客户 List<TestObject> newClients = newTestObjects.stream() .filter(client -> !existingClients.contains(client)) .collect(Collectors.toList()); // 合并列表 List<TestObject> mergedList = new ArrayList<>(testObjects); mergedList.addAll(newClients);
2. 更简洁的合并去重方式:用LinkedHashSet保留顺序
如果需要保留原有客户的顺序,同时自动去重,LinkedHashSet是最佳选择——它既遵循equals/hashCode的去重规则,又能维护元素的插入顺序,几行代码就能完成合并:
Set<TestObject> mergedSet = new LinkedHashSet<>(testObjects); mergedSet.addAll(newTestObjects); List<TestObject> mergedList = new ArrayList<>(mergedSet);
3. 大数据量场景:数据库层面去重
如果客户数据量较大,不建议全量加载到内存处理,直接在数据库层面做优化更高效:
- 给
phone_number和email字段建立联合唯一索引,数据库会自动拦截重复数据 - 使用批量插入语法:
- MySQL:
INSERT INTO clients (phone_number, email, name) VALUES (...) ON DUPLICATE KEY UPDATE name = VALUES(name);(需更新重复项字段时),或者INSERT ... ON DUPLICATE KEY IGNORE;(直接跳过重复项) - PostgreSQL:
INSERT INTO clients (phone_number, email, name) VALUES (...) ON CONFLICT (phone_number, email) DO NOTHING;
这种方式无需在代码中处理去重逻辑,性能更优。
- MySQL:
关于TestObject的equals/hashCode实现
你已经正确重写了这两个方法,仅用手机号和邮箱作为重复判定依据,完全符合需求,不需要调整。
内容的提问来源于stack exchange,提问作者Ivan Dvurechenskiy
相关产品推荐
相关产品推荐

