In our application I often see generated equals and hashCode methods. I don't know why they are overriden however I am worried about that they are generated (I think so as the are very similar). The below example shows the problem. One SomeBean instnace is created and it firlsty exists and then the set doesnt containt this object. It is because the change of "a" value and hashcode is changed. HashSet caches hashcodes wright? So every change of an objec previously put in Hashset is dangerous?
private class SomeBean{
private Integer a = 0;
public void setA(Integer a) {
this.a = a;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SomeBean someBean = (SomeBean) o;
if (a != null ? !a.equals(someBean.a) : someBean.a != null) return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + a.hashCode();
return result;
}
}
@Test
public void test() throws Exception {
SomeBean sb = new SomeBean();
Set set = new HashSet<>();
set.add(sb);
sb.hashCode();
System.out.println( set.contains(sb));;
sb.setA(4);
System.out.println(set.contains(sb));;
}
Should the hashCode be cached by SomeBean class and never changed? It could look like this:
@Override
public int hashCode() {
if (_hashCode == 0) {
final int prime = 31;
int result = 1;
result = prime * result + a.hashCode();
return result;
} else return _hashCode;
}
}
But now I risk that object with "a" = 0 and every other new object created with "a"=0 and then changed are the same objects..
It won't work. The reason for that is that HashSet is based on the assumption that hash code of an object won't change, but you change value of your object:
that changes the value of a hash code.
Internally hash map is based on an array. Hash code is used to select a position in an array that is used for hash-map implementation and since hash-code is changed from one call to another HashSet is looking into a different position in the array. Since another element in the array is empty HashSet assumes that such element does not exists in the datastructure.