I would like to generate a hash-code for the following equals-method.
public MyClass class {
private int a;
private final String b;
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MyClass)) return false;
MyClass myClass = (MyClass) o;
return a == myClass.a || (b == null ? myClass.b == null : b.equals(myClass.b));
}
@Override
public int hashCode() {
int result = (int) (a^ (a >>> 32));
result = 31 * result + (b != null ? b.hashCode() : 0);
return result;
}
}
The catch is that equals returns true in a single or both of 2 cases: either o1.a == o2.a or o1.b == o2.b. In such a case usual hash won't be the same for: myClass("a", "b") and myClass("a", null)
Forget the hash - your equality comparison is fundamentally broken to start with.
Consider three values:
foo: a=10, b=0
bar: a=10, b=5
baz: a=20, b=5
Now:
foo.equals(bar) => true because of a
bar.equals(baz) => true because of b
foo.equals(baz) => false because neither a nor b match
This violates the transitivity requirements of Object.equals
:
for any non-null reference values
x
,y
, andz
, ifx.equals(y)
returnstrue
andy.equals(z)
returnstrue
, thenx.equals(z)
should returntrue
.
If you don't have transitivity, it's going to be really hard to come up with a valid hashCode
implementation other than returning a constant (which is valid, but not exactly useful).
See more on this question at Stackoverflow