sandhya sasane
sandhya sasane

Reputation: 1352

HashSet behaviour is surprising

I have searched for this on stackoverflow and found unrelated threads for this case. I have also tried on my own, and will keep trying until the solution. But it will be good if someone shows me if i am doing any mistakes in code.


I am having a HashSet so that i can keep away duplicate strings from being getting added to it. And if HashSet is adding then it must be a unique string.


My class declarations are :

public List<String> ContactsList;
public List<String> ContactsNumbersList;

My code to fetch contacts and adding it into these two lists by taking help of HashSet so that i keep duplicate numbers away is :

    ContactsList = new ArrayList<String>();
    ContactsNumbersList = new ArrayList<String>();

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

    // Contacts Database queries

    Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}, null, null,  ContactsContract.CommonDataKinds.Phone.SORT_KEY_PRIMARY +" ASC");


    while (cursor.moveToNext())
    {
        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        String phoneNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

        if (normalizedNumbersAlreadyFound.add(phoneNumber))
        {
            phoneNumber = phoneNumber.replace("-","");
            phoneNumber = phoneNumber.replace(" ","");
            phoneNumber = phoneNumber.replace("(","");
            phoneNumber = phoneNumber.replace(")","");
            ContactsList.add(name);
            ContactsNumbersList.add(phoneNumber);
        }

    }
    cursor.close();

Well then why my ContactsNumbersList having duplicate entries...? Thanking you in advance for any suggestions.. which will help me.

Upvotes: 0

Views: 66

Answers (1)

Mena
Mena

Reputation: 48444

There seems to be a problem with your design.

First and foremost, you don't need Lists if your goal is to use a collection without duplicates.

Just use your Set instead.

Secondly, and specifically to your code, you are checking whether the element is added to your Set before normalizing it and adding the normalized String to the List.

Therefore, it may very well be that your List will contain duplicates because two elements that differ before normalization may be equal after normalization.

This leads me back to advise you to use your Set directly and disregard using a List in this use case.

Example

List<String> source = Arrays.asList("123-456789", "(1)23456789");
System.out.printf("Source List contains: %s%n", source);
Set<String> set = new HashSet<>();
List<String> unnecessary = new ArrayList<>();
Set<String> useful = new HashSet<>();

for (String s: source) {
    if (set.add(s)) System.out.printf("Added %s to set.%n", s);
    s = s.replaceAll("[()-]", "");
    System.out.printf("\t... now normalized to %s%n", s);
    // s is now normalized
    unnecessary.add(s);
    useful.add(s);
}
System.out.printf(
    "Set contains %s.%nUnnecessary List contains %s.%nUseful Set contains %s.%n", 
    set, 
    unnecessary,
    useful
);

Output

Source List contains: [123-456789, (1)23456789]
Added 123-456789 to set.
    ... now normalized to 123456789
Added (1)23456789 to set.
    ... now normalized to 123456789
Set contains [(1)23456789, 123-456789].
Unnecessary List contains [123456789, 123456789].
Useful Set contains [123456789].

Upvotes: 8

Related Questions