I have an ArrayList in Java which is made up of a type containing two strings and an integer. I can successfully test if one element of this ArrayList equals another but I find that the contains method fails. I believe this is due to the fact that my type is not primitive.
Now I see two alternatives to this and I wonder which is the best option:
To implement my own contains method by iterating through the ArrayList and testing equality of each element against the one I'm looking for and then breaking the loop.
Or to use a HashMap of my type as key with an integer as value instead of the ArrayList. Here I can use method containsKey to check if an element already exists in the HashMap.
The only caveat with approach to #2 is that the value is largely redundant in my case.
Did you override the equals method? This is required to make contains work correctly.
Remember that if you don't override the equals() method, then two objects of your type are only equal if they are the same instance of that object. The ArrayList class uses this method to check that it contains the given object. Also, you need to match the signature exactly, which means that it must take an Object as a parameter and not a Foo.
Also, the Object contract stipulates that you must override hashCode() whenever you override equals(). If you don't do this, then a HashMap or HashSet won't identify your two objects as being equal, even if the ArrayList does (HashMap checks for identical hashes and then calls equals() on them to check for actual equality). Thus, if ArrayList says that two items aren't equal, then there is no way that HashMap would either. This means that your second solution does not work.
My recommendation is to check that you actually override equals() and hashCode() properly and that their signatures match the ones in the Object class.
My guess is that you've only written a "strongly typed" equals method instead of overriding equals(Object). In other words, if you've got:
you need
as well to override Object.equals.
That would fit with "equals works but contains doesn't because your tests probably call the strongly-typed equals, but ArrayList doesn't.
Most likely, you have simply forgotten to override
equals()
andhashCode()
in your type.equals()
is whatcontains()
checks for.From the Javadoc:
Since the default implementation of
equals
tests for reference equality, it's not suitable for custom data types like this one.(And if you didn't override
equals
andhashCode
, using your types as keys in aHashMap
would be equally futile.)Edit: Note that to override, you must provide the exact signature.
This is a very strong argument for using the
@Override
annotation; the first example would have failed at compile time if annotated with@Override
.maybe use the Integer class instead? then you can do object comparison