i have a class whose equality is based on 2 fields such that if either one is equal then the objects of this type are considered equal. how can i write a hashCode() function for
I think you can't. The reason is, your equals()
method is not transitive.
Transitivity means for three non-null x, y, z, if x.equals(y)
, y.equals(z)
, then x.equals(z)
. In your example, an object x={id: 1, name: "ha"}
, y={id: 1, name: "foo"}
, z={id: 2, name: "bar"}
have this property (x.equals(y) and y.equals(z))
. However, x.equals(z)
is false
. Every equals()
method should have this property, see the Java API docs.
Back to hashing functions: Every function yields an equivalence defined by f(x)==f(y)
. That means if you are interested in comparison of the function values and want it to return true if x==y
(and possibly in other cases), you'll receive a transitive relation, which means you have to consider at least a transitive closure of objects' equivalence. In your case, the transitive closure is the trivial relation (everything equals to anything). Which means you can't distinguish different objects by any function.
How about
public override int GetHashCode()
{
return id.GetHashCode() ^ name.GetHashCode();
}
The simplest route is to XOR the hashcodes of each individual field. This has minor ugliness in some situations (e.g. in X,Y coordinates, it causes the potentially poor situation of having equal hashes when you flip X and Y), but is overall pretty effective. Tweak as needed to reduce collisions if necessary for efficiency.
I'm pretty sure Zach's right - there's no non-trivial hashcode to do this.
Pseudo-proof:
Consider any two non-equal values, X=(id1, name1) and Y=(id2, name2).
Now consider Z=(id2,name1). This is equal to both X and Y, so must have the same hashcode as both X and Y. Therefore X and Y must have the same hashcode - which means all values must have the same hashcode.
There's a reason why you've got into a weird situation - you're breaking the transitive nature of equals. The fact that X.equals(Z) and Z.equals(Y) should mean that X.equals(Y) - but it doesn't. Your definition of equality isn't suitable for the normal contract of equals.