6

I have a scenario in my code where I need to compare two Lists and remove from the first list, objects which are present in the second list. Akin to how the "removeAll" object works for List. Since my List is created on a custom object, the removeAll method won't work for me.

I have tried various methods to make this work: - implemented equals() and hashCode for the custom object comprising the list - implemented the Comparable Interface for the custom object - implemented the Comparator Interface for the custom object

I've even tried using the Apache Common's CollectionUtils and ListUtils methods (subtract, intersect, removeAll). None seem to work.

I understand I will perhaps need to write some custom removal code. But not sure how to go about doing that. Any pointers helping me move in the right direction will be really appreciated.

Thanks, Jay

Jay
  • 61
  • 1
  • 1
  • 2
  • 3
    for a start, give some code so that we don't guess – Bozho Apr 11 '10 at 14:39
  • I think the question might be clearer if you could show the code for what you are trying to do. – ig0774 Apr 11 '10 at 14:47
  • It's been suggested here and below, but specifically please post the code for your `equals` and `hashCode` methods. You probably tried these but wrote them incorrectly. This is the correct approach and will work with `removeAll()` if done right. – Kevin Brock Apr 11 '10 at 17:07

4 Answers4

14

Java Collections already cater for your scenario. Call Collection.removeAll(Collection) and it'll remove all the items from the passed in collection using the equals() method to test for equality.

List<String> list1 = new ArrayList<String>();
Collections.addAll(list1, "one", "two", "three", "four");
List<String> list2 = new ArrayList<String>();
Collections.addAll(list2, "three", "four", "five");
list1.removeAll(list2); // now contains "one", "two"

To make this work the objects you're storing just need to properly implement the equals/hashCode contract, which is: given any two objects a and b:

a.equals(b) == b.equals(a)

and:

a.hashCode() == b.hashCode() if a.equals(b)

Improperly defined equals and hashCode methods create undefined behaviour and are the common cause of collections related issues.

cletus
  • 578,732
  • 155
  • 890
  • 933
  • @Cletus: he actually says (a little below) that he tried and it didn't work for him. – Roman Apr 11 '10 at 14:41
  • 8
    @Roman until he posts some code I don't believe it. More than likely it will come down to something like incorrect use of the API or violating the equals/hashCode contract, etc. – cletus Apr 11 '10 at 14:44
  • This sure was my problem. Regenerated equals and hashCode then things started working again. Thanks :-) – Avec May 20 '14 at 10:55
6

Overriding equals and hashCode methods is enough to make method removeAll work on custom objects.

It's likely that you didn't override them in a proper way. Some code will help us a lot.

Roman
  • 59,060
  • 84
  • 230
  • 322
4

You said:

... Since my List is created on a custom object, the removeAll method won't work for me.

As others have stated, .removeAll() should work for the scenario you described, even for custom objects, as long as the custom objects obey the contracts that Java Collections expects of its objects, including a properly implement equals() and hashCode() method.

I have tried various methods to make this work: - implemented equals() and hashCode for the custom object comprising the list - implemented the Comparable Interface for the custom object - implemented the Comparator Interface for the custom object ...

It sounds like your are shot-gunning different approaches: coding one, trying it, quickly coding another, trying it, coding yet another, ... It make be worthwhile to slow down and try to understand why each approach failed and/or determine why that approach won't work for your situation, before moving on to the next. If you've already investigated and determined why each approach won't work, please explain in your question. If you haven't, then let us help by posting code.

Since most people agree the first approach (.removeall()) should have work and since custom objects are involved, why not take a quick review of this StackOverflow question to see if anything jumps out of you:

Overriding equals and hashCode in Java

"What issues / pitfalls do I need to consider when overriding equals and hashCode in a java class?"

Community
  • 1
  • 1
Bert F
  • 78,021
  • 11
  • 97
  • 121
0

I have found that his original statement it true. removeAll works automatically only if you override the remove in the iterator. Just overriding the remove in the Collection is not enough because the removeAll (and clear and retainAll) all use the iterator to work. Since you should not change the underlying collection while using the iterator except for the remove in the iterator, if you do not override the remove in the iterator, the removeAll, clear and retainAll will not work. If you throw an UnsupportedOperationException in the remove method inside the iterator, that is what you will see if you call one of the three methods discussed.