ArrayList use equals() in its contains method to see if provide object equals any item in the list as the document say:
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)). see this
I have this class
class Foo
{
private String value;
public Foo(String value)
{
this.value = value;
}
@Override
public boolean equals(Object o)
{
return o == null ? this.value == null : o.toString().equals(this.value);
}
}
I want to use contains method to check if item exists like this
List<Foo> list = new ArrayList<Foo>();
Foo item1 = new Foo("item1");
Foo item2 = new Foo("item2");
list.add(item1);
list.add(item2);
System.out.println(item1.equals("item1")); //return true
System.out.println(list.contains("item1")); //false !! why?!
but contains method return false , while item1.equals("item1") return true.
why contains return false when it use equals method for provided object
Your equals() implementation violates the symmetric principle :
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
item1.equals("item1") returns true
while
"item1".equals(item1) returns false.
So you should not expect that Collection method such as contains() works in a consistent way.
As a general rule, equals() overriding should not try to interoperate with other classes but only with instances of the underlying class.
In your case, it works only for String parameter passed to the method.
You should rather make it working for Foo instances parameter:
@Override
public boolean equals(Object o) {
if (!(o instanceof Foo){
return false;
}
Foo other = (Foo) o;
return Objects.equals(other.value, this.value);
}
Your problem is that your equality is not symmetric. Foo == String does not imply String == Foo.
If you look at the implementation of ArrayList.contains you'll see that it calls objectToFind.equals(objectInList), which may be contrary to what you were expecting:
o.equals(elementData[i])
So in your case that's String.equals(Foo). Because String.equals will return false for anything that's not a String, ArrayList.contains returns false.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With