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