I am making a complex number class in Java as follows:
public class Complex { public final double real, imag; public Complex(double real, double imag) { this.real = real; this.imag = imag; } ... methods for arithmetic follow ... }
I applied the equals method as follows:
@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; }
But if you override equals, you must also override hashCode. One of the rules:
If two objects are equal according to the equals (Object) method, then calling the hashCode method for each of the two objects should give the same integer result.
Comparing float and double with == makes a numerical comparison, so the values +0.0 == -0.0 and NaN are unequal to everything, including ourselves. So I tried to implement the hashCode method to match the equals method as follows:
@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); }
But then I realized that it would work weird in a hash map if any field is NaN, because this.equals(this) will always be false, but maybe this is not true. On the other hand, I could do what double and float do, where the equals methods compare +0.0 != -0.0 , but still agree on different NaN bit patterns and allow NaN == NaN , so I get:
@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); }
But if I do this, then my complex numbers do not behave like real numbers, where +0.0 == -0.0 . But I still donβt need to put my complex numbers in hash cards - I just want to do the right thing, follow the best practices, etc. And now I'm just embarrassed. Can someone advise me on the best way to continue?