Xeno raised the use of Double.compare to be used to test for equality of floating point values instead of ==.
This should only be done if -0.0 and 0.0 are considered different. If this is the case then the accompanying hashCode value should not use Double.hashCode since when two objects are equal they must have the same hash code. This is not the case for: EpsilonDoublePrecisionContext Vector1D Vector2D Vector3D SphericalCoordinates PolarCoordinates When some of the numbers are 0.0 (or -0.0) as they use == for equality then their hash codes are different. In the cases of: AffineTransformMatrix2D AffineTransformMatrix3D AxisAngleSequence When the doubles are 1 ulp apart they are equal as they use Precision.equals for equality but they will have a different hash code. (Note that AffineTransformMatrix1D does not use Precision.equals but Double.compare == 0 so is fine.) I think I have found all the cases of a broken hashCode but a search should be made for Double.hashCode and check all the hashCode and equals implementations are consistent. If Precision.equals is to be used in the equals method then it will require some changes to have a correct hashCode implementation. There are 3 options: 1. Document the inconsistency In this case the class should be documented as being inconsistent with the hashCode contract, something like: <p>Note: This class has a hashCode that is inconsistent with equals. 2. Switch to binary equality Provide a binary equality in equals and then a second method for equals using a precision context. 3. Smarter hashCode functions For the case where 0.0 == -0.0 is to be used in equals then the hash code can be produced using: Double.hashCode(0.0 - x); Since: +0.0 - +0.0 = +0.0 +0.0 - -0.0 = +0.0 All other non-Nan values will have the sign inverted for the argument to hashCode and NaN will remain NaN. For the cases using Precision, IIUC the Precision.equals is always used with an allowed 1 ulp difference. So the following would work: Long.hashCode(Double.doubleToLongBits(0.0 - x) >>> 2); This should discard the least significant 2 bits thus any differences of 1 ulp will be discarded from the number. Note I’ve not tested this approach. Alex
