有重复的联系人名单为什么要排序?

5

我已将我的手机联系人按顺序列入一个数组列表中,但是在列表中有很多相同联系人名称的重复项。为什么会出现这种情况?如何避免这种情况发生?

以下是我尝试过的方法:

  cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null,
                "(" + ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + ") ASC");

  while (cursor.moveToNext()) {

        try {

            name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            phonenumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            contact_names_list.add(name);
            phone_num_list.add(phonenumber);


        } catch (Exception e) {
            e.printStackTrace();
        }

有人可以帮忙吗?

3
你可以使用 HASHSET - IntelliJ Amiya
1
有任何示例吗? - Jack
1
联系人是否属于多个分组?例如,同时在SIM卡和Google通讯录中。 - Tigger
是的,一些联系人在同一组中,但并非所有联系人都在其中。在这里,我得到了每个联系人名称超过2个重复。 - Jack
7个回答

6

这里似乎没有人回答你的问题。

你看到重复联系人的原因是你在查询电话而不是联系人

在Android中,有三个主要的表:

  1. Contacts 表 - 每个联系人有一项
  2. RawContacts 表 - 每个帐户每个联系人有一项(如Google、Outlook、Whatsapp等)- 多个 RawContacts 链接到单个 Contact
  3. Data 表 - 每个详细信息有一项(姓名、电子邮件、电话、地址等)- 每个数据项链接到一个 RawContact,多个 Data 行链接到每个 RawContact

你正在查询 CommonDataKinds.Phone.CONTENT_URI,它是 Data 表的一部分,所以如果一个联系人有多个电话和/或来自多个来源(例如 Google 和 Whatsapp)的相同电话,则你将会获得相同的电话与相同的 CONTACT_ID 多次。

解决方案是使用一个 HashMap(而不是 HashSet),其中键是 CONTACT_ID,这样你就可以显示每个联系人的多个电话:

String[] projection = new String[] { CommonDataKinds.Phone.CONTACT_ID, CommonDataKinds.Phone.DISPLAY_NAME, CommonDataKinds.Phone.NUMBER };
Cursor cursor = getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI, projection, null, null, null);

HashMap<Long, Contact> contacts = new HashMap<>();

while (cursor.moveToNext()) {
    long id = cursor.getLong(0);
    String name = cursor.getString(1);
    String phone = cursor.getString(2);

    Contact c = contacts.get(id);
    if (c == null) {
        // newly found contact, add to Map
        c = new Contact();
        c.name = name;
        contacts.put(id, c);
    }

    // add phone to contact class
    c.phones.add(phone);
}
cursor.close();


// simple class to store multiple phones per contact
private class Contact {
    public String name;
    // use can use a HashSet here to avoid duplicate phones per contact
    public List<String> phones = new ArrayList<>(); 
}

如果你想按名称对HashMap进行排序:

List<Contact> values = new ArrayList<>(contacts.values());
Collections.sort(values, new Comparator<Contact> {
    public int compare(Contact a, Contact b) {
        return a.name.compareTo(b.name);
    }
});

// iterate the sorted list, per contact:
for (Contact contact : values) {
    Log.i(TAG, "contact " + contact.name + ": ");
    // iterate the list of phones within each contact:
    for (String phone : contact.phones) {
        Log.i(TAG, "\t phone: " + phone);
    }
}

你做得很好,这个方案是我问题的完美解决方案。感谢您的支持。 - Jack
我该如何获取一个已排序的列表?我尝试了TreeMap,但它没有正确排序。 - Jack
你可以从 HashMap 中获取值,返回一个 ArrayList,然后对这个 ArrayList 进行排序,具体可见我的更新。 - marmor
当我这样排序时,如何获取每个联系人对应的电话号码以正确的顺序? - Jack
你能帮我吗? - Jack

3
你可以尝试使用 HashSet

public class HashSet extends AbstractSet implements Set, Cloneable, Serializable

  • 不允许重复的值。

代码结构

 HashSet<String> hashSET = new HashSet<String>();
        hashSET.add("AA");
        hashSET.add("BB");
        hashSET.add("CC");
        hashSET.add("AA"); // Adding duplicate elements

然后

Iterator<String> j = hashSET.iterator();
        while (j.hasNext())
            System.out.println(j.next()); // Will print "AA" once.
    }

现在使用TreeSet对你的Hashset值进行排序。

TreeSet实现了SortedSet接口,因此不允许重复的值。

 TreeSet<String> _treeSET= new TreeSet<String>(hashSET);

1
谢谢,它有效了,但是我失去了列表的排序顺序。 - Jack
现在我有一个未排序的联系人列表,所以我无法为每个联系人识别联系人号码。 - Jack
@Gibs 使用 TreeSet - IntelliJ Amiya
1
好的,谢谢你,我会尝试一下。我接受你的答案,因为它解决了重复问题。 - Jack
让我们在聊天中继续这个讨论。点击此处进入聊天室 - Jack
显示剩余3条评论

2

可能您的联系人有多个群组,其中一个群组是WhatsApp、Google等。请转到您的联系人并搜索具有WhatsApp帐户的联系人。将显示具有不同组的双重条目。

您应该使用或更改您的ContactsBean,在您的Bean中使用HashSet

注意: HashSet可以避免重复条目更多信息

HashSet仅包含唯一元素,它可以避免相同的键元素从HashSet中获取

示例bean

public class ContactBean {
    private HashSet<String> number = new HashSet<String>(); 

    public void setNumber(String number) {
        if (number == null)
            return; 
        this.number.add(number.trim()); 
    }

    public HashSet<String> getNumber() {
        return this.number; 
    }
}

简单示例

//Creating HashSet and adding elements  
  
  HashSet<String> hashSet=new HashSet<String>();  
  hashSet.add("Dhruv");  
  hashSet.add("Akash");  
  hashSet.add("Dhruv");   //Avoiding this entry   
  hashSet.add("Nirmal");  

 //Traversing elements  
 
  Iterator<String> itr = hashSet.iterator();  
  while(itr.hasNext()){  
   System.out.println(itr.next());
} 

1
我不知道为什么您从联系人中获取到了重复的项目,可能是电话联系人已经有了重复的值。您可以在“联系人”应用程序中检查。

无论何时想要避免重复项,都应该使用set数据结构。您可以在此处找到更好的解释和示例。

1

你可以使用 HashSet 来避免重复:

HashSet<String> hset = 
               new HashSet<String>();

您可以在 HashSet 中添加类似于 ArrayList 的内容:

hset.add(your_string);

将您的 ArrayList 转换为 HashSet:-
Set<String> set = new HashSet<String>(your_arraylist_object);

HashSet 避免重复条目 :)


谢谢您的回答,但我的问题是如何在排序时避免重复,有什么帮助吗? - Jack
在排序后将你的ArrayList转换为HashSet :) - Subhash Prajapati
请检查更新后的答案,它从ArrayList中删除了重复项 :) - Subhash Prajapati

0

我认为你的重复是因为Whatsapp联系人干扰了联系人。所以你可以使用类似这样的东西

                      String lastPhoneName = "";
                     String lastPhoneNumber = "";

                    //IN YOUR CONTACT FETCHING WHILE LOOP , INSIDE TRY 
                   String contactName = c.getString(c
                                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    String phNumber = c
                            .getString(c
                                    .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

                    if (!contactName.equalsIgnoreCase(lastPhoneName) && !phNumber.equalsIgnoreCase(lastPhoneNumber)) {

                        lastPhoneName = contactName;
                        lastPhoneNumber = phNumber;

                        ContactModel model = new ContactModel();
                        model.setContact_id(contactid);
                        model.setContact_name(contactName.replaceAll("\\s+", ""));
                        model.setContact_number(phNumber.replaceAll("\\D+", ""));


                        list_contact_model.add(model);

                    } 

这将检查前一个数字是否与旧数字相同,如果相同则跳过它。我希望你得到了答案。


0

HashSet 可以将项目添加为键/值对,并从项目集中删除重复条目。

List<String> phone_num_list= new ArrayList<>();
// add elements to phone_num_list, including duplicates
Set<String> hs = new HashSet<>();
hs.addAll(phone_num_list);
phone_num_list.clear();
phone_num_list.addAll(hs);

编程愉快!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接