-1

I am working in an Contact app where i have to list all the contacts from Contacts Database, but it contains duplicates.

For example, Contact number (98*******33, +9198********33) is listed as duplicates.

I have used Set, Checked whether my list contains the phone number before adding but none of this works !

ContactVO is the Pojo class and contactVoList is the list that i am adding contacts.

   Cursor phones = getContext().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
            while (phones.moveToNext()) {
                name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).replace(" ", "");
                imageUri = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
                System.out.println("Name and Phone number = " + name + phoneNumber + imageUri);

                if (contactVOList.size() == 0) {
                    contactVOList.add(new ContactVO(imageUri, name, phoneNumber, false));
                } else {
                    if (!contactVOList.contains(phoneNumber)) {
                        contactVOList.add(new ContactVO(imageUri, name, phoneNumber, false));
                    }
                }

                System.out.println("List size before removing duplicates =" + contactVOList.size());
            }

            Set<ContactVO> s = new HashSet<ContactVO>();
            s.addAll(contactVOList);
            contactVOList = new ArrayList<ContactVO>();
            contactVOList.addAll(s);

My Pojo class

public class ContactVO {
    private String ContactImage;
    private String ContactName;
    private String ContactNumber;
    private int hashCode;
    String id;
    boolean clicked;

    public ContactVO(String id) {
        this.id = id;
    }

    public boolean isClicked() {
        return clicked;
    }

    public void setClicked(boolean clicked) {
        this.clicked = clicked;
    }

    public String getId() {


        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public ContactVO(String ContactImage, String ContactName, String ContactNumber, Boolean clicked) {
        this.ContactImage = ContactImage;
        this.ContactName = ContactName;
        this.ContactNumber = ContactNumber;
        this.clicked = clicked;
    }


    public String getContactImage() {
        return ContactImage;
    }

    public void setContactImage(String contactImage) {
        this.ContactImage = ContactImage;
    }

    public String getContactName() {
        return ContactName;
    }

    public void setContactName(String contactName) {
        ContactName = contactName;
    }

    public String getContactNumber() {
        return ContactNumber;
    }

    public void setContactNumber(String contactNumber) {
        ContactNumber = contactNumber;
    }

    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stubs
        if (obj instanceof ContactVO) {
            ContactVO temp = (ContactVO) obj;
            System.out.println("this.getctno" + this.getContactNumber());
            System.out.println("temp.getctno" + temp.getContactNumber());
            if (this.getContactNumber() == temp.getContactNumber() && this.getContactName() == temp.getContactName() && (this.getContactNumber()).contains(temp.getContactNumber()))
                return false;
        }
        return true;
    }

    @Override

    public int hashCode() {
        // TODO Auto-generated method stub
        return (this.getContactNumber().hashCode() + this.getContactName().hashCode());
    }
}
James Z
  • 12,209
  • 10
  • 24
  • 44
KarthikKPN
  • 653
  • 12
  • 22
  • You are already using `Set` which is the solution . Have look into [This thread](https://stackoverflow.com/questions/16462644/java-duplicate-objects-getting-added-to-set) for custom object implementation of Set. – ADM Jan 07 '18 at 06:57
  • @ADM Yes, but also the duplicates is not being removed. – KarthikKPN Jan 07 '18 at 06:58
  • Thats because you are using a custom class. you have override `Object` methods. have a look into solution above . – ADM Jan 07 '18 at 06:59
  • @ADM, i have edited my question and added the pojo class. Can you please check it once. I have already over rided equals() and hashcode() methods. – KarthikKPN Jan 07 '18 at 07:02
  • Your `equals` method contains several errors. For example you compare strings with `==` instead of `equals`; if the other object is of an unrelated class you return `true`; it seems the return value is generally the negation of what it should be,... – Henry Jan 07 '18 at 07:07
  • @ADM, I edited my code following your answer, but i again contains the duplicates :( – KarthikKPN Jan 07 '18 at 07:14
  • You want a set of phone numbers, but what you created is a set of `ContactVO`. That means if you have two contacts with different names but the same phone number, you will get a duplicate phone number in the set. If you want a set of phone numbers, why don't you try creating a set of phone numbers? – Rainbolt Jan 07 '18 at 08:22
  • Or, change your `equals()` method to only compare phone numbers, and not care about the contact name. Then you would essentially be saying "Two `ContactVO`s are equivalent if they have the same phone number." If that's actually a true statement in the context of your application, then it's the better solution. – Rainbolt Jan 07 '18 at 08:27
  • By the way, when you post code that you didn't write, consider mentioning [the source](http://sonevalley.blogspot.com/2015/12/retrieving-list-of-contacts-in-android.html). – Rainbolt Jan 07 '18 at 08:33

4 Answers4

0

Modify equals as below.

 @Override
public boolean equals(Object obj) {
    if (obj instanceof ContactVO) {
        ContactVO temp = (ContactVO) obj;
        System.out.println("this.getctno" + this.getContactNumber());
        System.out.println("temp.getctno" + temp.getContactNumber());
        if (this.getContactNumber().equals(temp.getContactNumber()) &&
                this.getContactName().equals( temp.getContactName()))
            return true;
    }
    return false;
}
@Override
public int hashCode() {
    // TODO Auto-generated method stub
    return (this.getContactNumber().hashCode() + this.getContactName().hashCode());
}

One thing keep in mind numbers like "98*******33, +9198********33" are not Equals. If you want to test them for equality and return true then you have to modify equals(). Its not the ultimate solution . But you can give it a try .

 @Override
public boolean equals(Object obj) {
    if (obj instanceof ContactVO) {
        ContactVO temp = (ContactVO) obj;
        if(getContactNumber().length()>=temp.getContactNumber().length()){
            if (this.getContactNumber().endsWith(temp.getContactNumber()) &&
                    this.getContactName().equals( temp.getContactName()))
                return true;
        }else{
            if (temp.getContactNumber().endsWith(this.getContactNumber()) &&
                    this.getContactName().equals( temp.getContactName()))
                return true;
        }
    }
    return false;
}
ADM
  • 20,406
  • 11
  • 52
  • 83
0

Override equals and hashCode method in ContactVO class may work.

When you use HashSet, it will call the hashCode method of class to get the hash code of instance, then the HashSet will transfer the hash code to an index, the index is the location of the object. When you add a new object, it will get an index and check whether there is an object in the location, if not, it will add the object, else it will traverse the link list and call equals method to find same object, if there isn’t, the object will be appended to the link list.

Code Example:

@Override
public boolean equals(Object obj) { 
    ContactVO tmpContact= (ContactVO) obj; 
    if (phoneNumber.equals(tmpContact.phoneNumber)) return true; 
    else return false; 
} 

public int hashCode(){
     return phoneNumber.hashCode();
}
blanksky
  • 13
  • 4
0

try this...

    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stubs
        if (obj instanceof ContactVO) {
            ContactVO temp = (ContactVO) obj;
            System.out.println("this.getctno" + this.getContactNumber());
            System.out.println("temp.getctno" + temp.getContactNumber());
            if (this.getContactNumber().equals(temp.getContactNumber()) || this.getContactNumber().endsWith(temp.getContactNumber()) ||
            temp.getContactNumber().endsWith(this.getContactNumber()))
                return true;
        }
        return false;
    }
SRB Bans
  • 3,096
  • 1
  • 10
  • 21
0

The problem with the suggested solutions is, that they suppose that your "duplicates" are actually equal strings, which they are not.

You have "98*******33" and "+9198********33" as duplicates, but they are not equal strings.

So what you need to do prior to adding all of them to your set, is to normalize the phone numbers to a common, standard format. You will have to decide yourself what that should look like. I would suggest something like your second example: + without any spaces or dashes. If the country-prefix is missing for a number, you will have to assume some default or you can derive it perhaps from other information you have from the contact.

After this normalization, your first number would also be "+9198*******33" and the 'Set-Solution' will work as expected.

Ridcully
  • 23,362
  • 7
  • 71
  • 86