如何为有限精度的double值编写正确的hashcode方法?

问题描述 投票:1回答:1

如果double成员在另一个对象的给定范围内,则认为类Foo的对象是相等的。由于浮点运算,可以容易地引入这样的错误。

方法isDoubleEqualsdoubleArrayEquals将处理equals部分,但合同规定哈希码必须对于相等的对象是相同的。双精度的默认哈希码不会将close值映射到相同的值,因此为匹配双精度数获取相同哈希值的好方法是什么?

public class Foo {

    double[] values;

    public Foo(double[] values) {
        this.values = values;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        //TODO Arrays.hashCode will not work with the contract
        result = prime * result + Arrays.hashCode(values);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Foo other = (Foo) obj;
        if (!doubleArrayEquals(values, other.values,1e-10))
            return false;
        return true;
    }

    private boolean doubleArrayEquals(double[] arr, double[] arr2, double epsilon) {
        if (arr== arr2)
            return true;
        if (arr == null || arr2 == null)
            return false;

        int length = arr.length;
        if (arr2.length != length)
            return false;

        for(int i = 0; i < length; i++) {
            if(!isDoubleEquals(arr[i],arr2[i],epsilon)) {
                return false;
            }
        }
        return true;
    }

    private boolean isDoubleEquals(double needle, double target, double epsilon) {
        return Math.abs(needle - target) <= epsilon;
    }
}
java equals hashcode
1个回答
5
投票

你不能正确编写处理近似相等的equalshashCode方法。

equals的合同要求传递性,近似的平等不是传递性的。

这并不是说近似平等不是一个有用的东西:它不是Java的equals(和hashCode)方法的用途,因此你应该定义自己的方法 - 比如isApproximatelyEqualTo - 来支持它,而不会超载众所周知的Java方法。

© www.soinside.com 2019 - 2024. All rights reserved.