hashCode() method when equals() is based on multiple independent fields

前端 未结 10 2123
执念已碎
执念已碎 2021-02-08 09:16

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

相关标签:
10条回答
  • 2021-02-08 09:41

    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.

    0 讨论(0)
  • 2021-02-08 09:41

    How about

    public override int GetHashCode()
    {
        return id.GetHashCode() ^ name.GetHashCode();
    }
    
    0 讨论(0)
  • 2021-02-08 09:44

    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.

    0 讨论(0)
  • 2021-02-08 09:45

    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.

    0 讨论(0)
提交回复
热议问题