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 f
Did you override the equals method? This is required to make contains work correctly.
Most likely, you have simply forgotten to override equals()
and hashCode()
in your type. equals()
is what contains()
checks for.
From the Javadoc:
Returns
true
if this list contains the specified element. More formally, returnstrue
if and only if this list contains at least one elemente
such that(o==null ? e==null : o.equals(e))
.
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
and hashCode
, using your types as keys in a HashMap
would be equally futile.)
Edit: Note that to override, you must provide the exact signature.
class MyDataType {
public boolean equals(MyDataType other) { // WRONG!
...
}
public boolean equals(Object other) { // Right!
...
}
}
This is a very strong argument for using the @Override annotation; the first example would have failed at compile time if annotated with @Override
.
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:
public boolean equals(Foo f)
you need
public boolean equals(Object o)
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.
maybe use the Integer class instead? then you can do object comparison
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.