如何构建哈希码以支持对称性

Don*_*Don 1 java math vector

我写了一个PointPair类,它有4个双精度表示2点的坐标值,其中第一个点,A =(a1,a2),第二个点,B =(b1,b2).我在我的类中实现了hashCode和equals方法,并且一直运行良好,直到我被告知它需要支持对称性,即用A构建的PointPair对象,B需要等于用B,A构建的PointPair.

class PointPair {
    public final double a1, a2, b1, b2;

    public PointPair(Point a, Point b) {
        this.a1 = a.x; this.a2 = a.y;
        this.b1 = b.x; this.b2 = b.y;
    }

    public int hashCode() {
        return Objects.hash(a1, a2, b1, b2); // fix me!
    }

    private boolean bothEqual(double d1, d2) {
       return Double.compare(d1,d2) == 0 ;
    }

    public boolean equals(Object obj) {
        if ((obj == null) || !(obj instanceof PointPair))
            return false;
        PointPair pObj = (PointPair) obj;

        //test for same reference or value match
        return (obj == this) || (bothEqual(a1, pObj.a1) && bothEqual(a2, pObj.a2) && bothEqual(b1, pObj.b1) && bothEqual(b2, pObj.b2)) ||
                (bothEqual(a1, pObj.b1) && bothEqual(a2, pObj.b2) && bothEqual(b1, pObj.a1) && bothEqual(b2, pObj.a2)) ; // symmetry match
    }

}
Run Code Online (Sandbox Code Playgroud)

我改变了我的equals方法来支持它(请参见上文),但我正在寻找修复hashCode方法或类的其他方案的想法.我想到的一个想法是使用两个虚拟向量来计算点积指标,这两个向量表示点(几何思考)和它们之间的角度.这对于我的点对中的2点总能给出一个独特的值吗?

    public int hashCode() {
         double dotprod = (a1*b1)+(a2*b2) ;
         double mag1 = Math.sqrt(a1*a1+a2*a2)
         double mag2 = Math.sqrt(b1*b1+b2*b2)
         double angle = Math.acos(dotprod/(mag1*mag2))
         Objects.hash(dotprod, angle)
    }
Run Code Online (Sandbox Code Playgroud)

Rad*_*def 5

您可以通过添加来完成此操作.与您现有的风格相同hashCode,它将是:

Objects.hash(a1, a2) + Objects.hash(b1, b2)
Run Code Online (Sandbox Code Playgroud)

例如,这是如何java.util.Set指定它hashCode与订单无关.

另一种方法是使用XOR.

  • 在这种情况下你可以使用乘法,但除法和减法将不起作用.运算符必须是对称的,即必须是"a op b == b op a"的情况,对于除法和减法并不总是如此.您选择实施散列的很多方式取决于数据的样子.如果`a`和`b`通常很小,`a*b`会产生更少的碰撞.如果`a`和`b`通常很大,那么`a*b`可能会溢出. (2认同)