I am having an issue where I make an ArrayList of Foo objects, I override the equals method, and I cannot get the contains method to call the equals method. I have tried overriding equals and hashcode together, but it still doesn't work. I'm sure there is a logical explanation to why this is, but I cannot figure it out at the moment on my own lol. I just want a way to see if the list contains the specified id.
Here's some code:
import java.util.ArrayList;
import java.util.List;
public class Foo {
private String id;
public static void main(String... args){
Foo a = new Foo("ID1");
Foo b = new Foo("ID2");
Foo c = new Foo("ID3");
List<Foo> fooList = new ArrayList<Foo>();
fooList.add(a);
fooList.add(b);
fooList.add(c);
System.out.println(fooList.contains("ID1"));
System.out.println(fooList.contains("ID2"));
System.out.println(fooList.contains("ID5"));
}
public Foo(String id){
this.id = id;
}
@Override
public boolean equals(Object o){
if(o instanceof String){
String toCompare = (String) o;
return id.equals(toCompare);
}
return false;
}
@Override
public int hashCode(){
return 1;
}
}
OUTPUT: false false false
This is because your equals()
is not symmetric:
new Foo("ID1").equals("ID1");
but
"ID1".equals(new Foo("ID1"));
is not true. This violates the equals()
contract:
The equals method implements an equivalence relation on non-null object references:
[...]
It is symmetric: for any non-null reference values
x
andy
,x.equals(y)
should return true if and only ify.equals(x)
returnstrue
.
It is not reflexive either:
- It is reflexive: for any non-null reference value
x
,x.equals(x)
should return true.
Foo foo = new Foo("ID1");
foo.equals(foo) //false!
@mbockus provides correct implementation of equals()
:
public boolean equals(Object o){
if(o instanceof Foo){
Foo toCompare = (Foo) o;
return this.id.equals(toCompare.id);
}
return false;
}
but now you must pass instance of Foo
to contains()
:
System.out.println(fooList.contains(new Foo("ID1")));
System.out.println(fooList.contains(new Foo("ID2")));
System.out.println(fooList.contains(new Foo("ID5")));
Finally you should implement hashCode()
to provide consistent results (if two objects are equal, they must have equal hashCode()
):
@Override
public int hashCode() {
return id.hashCode();
}