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.
Advertisement
Answer
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.