我正在用 Java 制作一个复数类,如下所示:
public class Complex {
    public final double real, imag;
    public Complex(double real, double imag) {
        this.real = real;
        this.imag = imag;
    }
    ... methods for arithmetic follow ...
}
我实现了这样的equals方法:
@Override
public boolean equals(Object obj) {
    if (obj instanceof Complex) {
        Complex other = (Complex)obj;
        return (
            this.real == other.real &&
            this.imag == other.imag
        );
    }
    return false;
}
但是如果你覆盖equals,你也应该覆盖hashCode。规则之一是:
如果两个对象根据 equals(Object) 方法相等,则对两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果。
比较floats 和doubles with==进行数值比较,因此+0.0 == -0.0和 NaN 值不等于包括它们自己在内的所有内容。所以我尝试实现 hashCode 方法来匹配 equals 方法,如下所示:
@Override
public int hashCode() {
    long real = Double.doubleToLongBits(this.real); // harmonize NaN bit patterns
    long imag = Double.doubleToLongBits(this.imag);
    if (real == 1L << 63) real = 0; // convert -0.0 to +0.0
    if (imag == 1L << 63) imag = 0;
    long h = real ^ imag;
    return (int)h ^ (int)(h >>> 32);
}
但后来我意识到,如果任一字段为 NaN,这在哈希映射中会很奇怪,因为它this.equals(this)总是错误的,但也许这并不正确。另一方面,我可以在 equals 方法比较的地方做什么Double和做什么,但仍然协调不同的 NaN 位模式,然后 let ,所以我得到:Float+0.0 != -0.0NaN == NaN
@Override
public boolean equals(Object obj) {
    if (obj instanceof Complex) {
        Complex other = (Complex)obj;
        return (
            Double.doubleToLongBits(this.real) ==
                Double.doubleToLongBits(other.real) &&
            Double.doubleToLongBits(this.imag) ==
                Double.doubleToLongBits(other.imag)
        );
    }
    return false;
}
@Override
public int hashCode() {
    long h = (
        Double.doubleToLongBits(real) +
        Double.doubleToLongBits(imag)
    );
    return (int)h ^ (int)(h >>> 32);
}
但如果我这样做,那么我的复数就不会像实数那样表现,其中+0.0 == -0.0. 但无论如何,我真的不需要将我的复数放在哈希图中——我只想做正确的事情,遵循最佳实践等。现在我很困惑。谁能告诉我最好的方法?