0

I have a bunch of users that I've put into a list, then I have another set of a bunch of users I've added to a separate list. I am trying to compare the first list of objects to the second list and create a new list of the unique objects.

        // List creation (new, old, unique)
        List<User> listNew = new ArrayList<User>();
        List<User> listOld = new ArrayList<User>();
        List<User> listUnique = new ArrayList<User>();

  ...

   for (User unique : listNew) {
        if (!listOld.contains(unique)) {
            listUnique.add(unique);
        }
    }

So I have this code to do that, but it just duplicates the listNew. How could I compare objects to one another? My class file is

public class User {

    private String fName;
    private String mInitial;
    private String lName;
    private String age;
    private String city;
    private String state;

....
Kenny
  • 2,124
  • 3
  • 33
  • 63

3 Answers3

3

You need to implement equals and hashCode in the User class. If you don't have these methods implemented in User, listOld.contains(unique) will only return true if listOld contains exactly the same instance referenced by unique.

Check this out for the difference between identity and equality in java: What is the difference between identity and equality in OOP?

Community
  • 1
  • 1
AlfredoCasado
  • 818
  • 5
  • 7
  • In addition, here is a relevant tutorial: http://tutorials.jenkov.com/java-collections/hashcode-equals.html – Radiodef Jan 27 '14 at 00:30
  • In Eclipse I auto generated `equals` and `hashCode` in the `User` class and my little loop still doesn't seem to detect that there are unique people in the _new_ users versus the _old_ users. Is auto generation a bad idea? – Kenny Jan 27 '14 at 00:57
  • If you don't understand the code eclipse is generating, yes its a bad idea. – AlfredoCasado Jan 27 '14 at 07:26
0

Sets have only unique elements by nature so that would be the correct type to use in your situation. First however you will need to properly override the hashcode() and equals() method of your User class. After that just try to add all instances to the a set and be done with it.

Set<User> uniqueUsers = new HashSet<User>();

for (User unique : listNew) {
    if (!listOld.contains(unique)) {
        uniqueUsers.add(unique);
    }
}
Bart
  • 17,070
  • 5
  • 61
  • 80
0

As other answers said, you need to override equals and hashCode.

You can use Collection.removeAll method.

First you need to wrap the listNew into a HasSet which ensure the uniquness.

Collection<User> newUniques = new HashSet<User>();
newUniques.addAll(listNew);
newUniques.removeAll(listOld);

Now your newUniques will have desired results.

If you can use the apache commons, ListUtils.removeAll(listNew, listOld) is another option.

Community
  • 1
  • 1
RP-
  • 5,827
  • 2
  • 27
  • 46
  • I _automatically generated_ `equals` and `hashCode` in my class and changed the unique list to a `Collection` but when I do the `removeAll` just like you suggested, it removes the entire list. Maybe I have a problem with the objects I created? – Kenny Jan 27 '14 at 02:48
  • Did you add all the `listNew` elements to newly created collection – RP- Jan 27 '14 at 03:19
  • Yes, I did `newUniques.addAll(listNew);` and it populates it with about the same amount that's in listNew (20,010), I do a system.out to check the size of `newUniques` then I run `newUniques.removeAll(listOld);` and the size changes to 0. – Kenny Jan 27 '14 at 03:26
  • `newUniques.removeAll(listOld);` will remove all the elements from `newUniques` which are there in `listOld`. If it is removing all the elements, then hope all `listNew` elements in `listOld` or there should be something wrong in hashCode or equals – RP- Jan 27 '14 at 03:36
  • In eclipse, I right clicked and through a few menus _auto-generated_ the hashCode and equals, so maybe that wasn't a good idea. Presently, I'm working to created my own, but don't really know what I'm doing, so I'm using this guide: http://tutorials.jenkov.com/java-collections/hashcode-equals.html – Kenny Jan 27 '14 at 03:54
  • If you change any property after the object is added to set, it is no more give you the actual hashCode and all the methods dependent on hashCode like `contains` will fail. Hope you are not modifying the values. – RP- Jan 27 '14 at 04:04
  • Never got it working, but I don't think I should make a new post. My equals is `@Override public boolean equals(Object o) { if(o == null) return false; if (getClass() != o.getClass()) return false; User other = (User) o; if(this.fName != other.fName) return false; if(! this.mInitial.equals(other.mInitial)) return false; if(! this.lName.equals(other.lName)) return false; if(! this.age.equals(other.age)) return false; if(! this.city.equals(other.city)) return false; if(! this.state.equals(other.state)) return false; return true; }` – Kenny Jan 27 '14 at 06:02