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

基于邮箱与手机号去重的客户列表合并:求更简便实现方案

客户列表去重合并的简便实现方式

我在数据库中存储了一份客户列表,需要实现该列表的更新功能并进行重复项校验。客户重复判定规则为对比邮箱与手机号,即仅添加邮箱和手机号均未在库中的客户,完成新旧列表合并。请问是否有更简便的实现方式?

现有实现代码

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;
      这种方式无需在代码中处理去重逻辑,性能更优。

关于TestObject的equals/hashCode实现

你已经正确重写了这两个方法,仅用手机号和邮箱作为重复判定依据,完全符合需求,不需要调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:23:17