Android - 删除重复的联系人

Android - Remove Duplicate Contacts

我正在尝试在 Recycler View 中显示联系人,一切正常,但联系人显示两次或三次。

这是代码

 RecyclerView recyclerView;
 List<Contacts> contactsList;
 ContactsAdapter adapter;

 public void getContactList() {
    Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null, null, null,
            "UPPER(" + ContactsContract.Contacts.DISPLAY_NAME + ") ASC");
    while (cursor.moveToNext()) {
        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

        Contacts contacts = new Contacts(name, number);
        if (contactsList.contains(contacts)){
            cursor.moveToNext();
        }
        else {
            contactsList.add(contacts);
        }
        adapter = new ContactsAdapter(contactsList, getApplicationContext());
        recyclerView.setAdapter(adapter);

        adapter.notifyDataSetChanged();
    }
}

那么,我该如何解决这个问题呢?

仅将 phoneNumber 作为键传递,将 phoneName 作为值传递 您可以使用:

Map<String, String> map = new HashMap<>();
map.put("A", "1");
...
System.out.printf("Before: %s%n", map);

// Set in which we keep the existing values
Set<String> existing = new HashSet<>();
map = map.entrySet()
    .stream()
    .filter(entry -> existing.add(entry.getValue()))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.printf("After: %s%n", map);  

例如:

Before: {A=1, B=2, C=2, D=3, E=3} After: {A=1, B=2, D=3}

您可以按照此页面上的这些步骤操作,我可以在此处提供完整的解决方案 link

我认为您应该考虑几个问题。是查询错误还是我保存联系人的方式不对?

在您的应用中是否应该允许重复联系人?如果否,您可以在迁移中添加 unique constraint。参见 Sql Lite Unique Constraints

如果您的数据库应该接受重复值,那么您应该添加一个列来表示该用户的唯一值?即 userId 列或联系人关联的位置,然后将其作为 Selection 和 SelectionArgs 添加到您的查询中。

最后,如果您只是想快速解决问题...您应该更深入地研究过滤。

您的代码 contactsList.contains(contacts) 永远不会正确,因为您总是在上面的行中创建联系人。然后您正在检查您的列表是否包含新创建的列表。否则你可以使用上面的解决方案

您可以覆盖 class 联系人中的 equals() 方法。这样,如果两个联系人对象在您的覆盖方法中逻辑上相等,则您的 contactList.contains(Contact c) 可以评估为真,因此它不会再次将其添加到列表中。

     @Override
     public boolean equals(Object o){
          if(!o.getClass().equals(Contacts.class)) return false;
          Contact c2 = (Contact)o;
          // if phonenumber is unique to differentiate contact
          return c2.number.equals(number);
      }

您可以将 List 更改为 HashSet。 HashSet 防止 有重复项。你的最终代码应该是这样的:

 RecyclerView recyclerView;
 HashSet<Contacts> contactsSet;
 ContactsAdapter adapter;

 public void getContactList() {
    Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null, null, null,
            "UPPER(" + ContactsContract.Contacts.DISPLAY_NAME + ") ASC");
    while (cursor.moveToNext()) {
        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

        Contacts contacts = new Contacts(name, number);
        contactsSet.add(contacts);
    }
    List<Contacts> contactsList = new ArrayList<>();
    adapter = new ContactsAdapter(contactsList, getApplicationContext());
    recyclerView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
}