Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I remove duplicate objects from two separate ArrayLists?

Before beginning, I think that this question has a very simple answer that I'm just overlooking. I figured a few more eyes on the question at hand will be able to point out my problem fairly quickly.

I have two ArrayLists that I want to compare and remove duplicates from each of them. The first ArrayList is an ArrayList of older information where as the second ArrayList contains the new information.

Like so

ArrayList<Person> contactList = new ArrayList();
contactList.add(new Person("Bob");
contactList.add(new Person("Jake");
contactList.add(new Person("Joe");
ontactList.add(new Person("Rob");

ArrayList<Person> updatedContactList = new ArrayList();
updatedContactList.add(new Person("Bob");
updatedContactList.add(new Person("Jake");
updatedContactList.add(new Person("Joe");
updatedContactList.add(new Person("Phil");

My Person class is very simple, created solely for this example

public class Person {
    private String name;

    public Person(String a_name) {
        name = a_name;
    }

    public String getName() {
        return name;
    }
}

So, using the above examples, I want to remove all duplicates. I'm trying keep it to just the two ArrayLists if possible, but am willing to do a deep clone of one of the ArrayLists if I have to.

So I want the resulting ArrayList to have the following information in it once the comparison is done

contactList           //removed Person
    - Rob

updatedContactList    //new Person
    - Phil

Here is the code I've put together

for(int i = 0; i < contactList.size(); i++) {
    for(int j = 0; j < updatedContactList.size(); j++) {

        if(contactList.get(i).getName().equals(updatedContactList.get(j).getName())) {
            //removed friends                    
            contactList.remove(contactList.get(i));

            //new friends ---- only one at a time works
            //updatedContactList.remove(updatedContactList.get(j));
        }
    }
}

I'm only able to remove a Person from one of the ArrayLists in the above loop otherwise I get incorrect results.

So my question is, is there an easy way to remove the duplicated elements from both ArrayLists? If so, how do I go about it.

I realize that I could probably deep clone the updated ArrayList and just remove the objects from that one, but I'm wondering if there is a way without having to clone it.

I also realize that I could just stuff all the elements into a Set and it would remove the duplicates, but I want to keep the 'removed' and 'new' Person objects separate.

like image 416
WilliamShatner Avatar asked Jun 03 '13 18:06

WilliamShatner


People also ask

Can Arraylists have duplicates?

Duplicates : ArrayList allows duplicate values while HashSet doesn't allow duplicates values. Ordering : ArrayList maintains the order of the object in which they are inserted while HashSet is an unordered collection and doesn't maintain any order.


2 Answers

What you really have is not lists, but sets: model both the old and the new contacts as a Set. Also implement equals and hashCode for your Person class to ensure proper operation.

Once you have that, you'll be able to write one-liners to calculate the set differences (which is what you need):

final Set<Person> contactsBackup = new HashSet<>(contacts);
contacts.removeAll(updatedContacts);
updatedContacts.removeAll(contactsBackup);

Note that this involves making one more copy, but it is not a deep copy—only references are copied. This is a very leightweight operation and you should not worry about its impact.

If, for some reason not at all obvious to me, you really need lists, the same code will work for them, too (List also defines removeAll), but you will have to live with O(n2) complexity this operation entails for lists.

like image 143
Marko Topolnik Avatar answered Sep 25 '22 07:09

Marko Topolnik


Override equals() and hashCode() in your Person class and simply do:

Set<Person> temp = new HashSet<>(contactList);
contactList.removeAll(updatedContactList);
updatedContactList.removeAll(temp);
temp.clear(); // not necessary if this code is in a method
like image 22
jlordo Avatar answered Sep 26 '22 07:09

jlordo