Javadoc 的equals
方法说明(强调我的):
https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-
equals 方法在非空对象引用上实现等价关系:
- 它是自反的:对于任何非空引用值 x,x.equals(x) 应该返回 true。
- 它是对称的:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
- 它是传递性的:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true 并且 y.equals(z) 返回 true,则 x.equals(z) 应返回 true。
- 它是一致的:对于任何非空引用值 x 和 y,如果对象的 equals 比较中使用的信息没有被修改,则多次调用 x.equals(y) 一致返回 true 或一致返回 false。
- 对于任何非空引用值 x,x.equals(null) 应返回 false。
相等方法必须是传递的。如果您使用了 epsilon,则这将不成立。
考虑双精度值 x = 2.0、y = 2.6、z = 3.1 和 epsilon = 1.0。
请注意,z - y = 0.5 和 y - x = 0.6,两者都小于 epsilon 1.0。然而,z - x = 1.1,即more比1.0。
因此,我们会有“x 等于 y”和“y 等于 z”,但没有“x 等于 z”,这会破坏传递性。如果这些是某些其他对象的实例变量(例如上面示例中的里程表),也会发生同样的情况。
因此,相等应该是精确的。如上所述转换为位,就像使用一样Double.compare(double d1, double d2)
或将它们转换为 Double 值,然后使用Double.compareTo(Double anotherDouble)
。请注意,它们会将 0.0 和 -0.0 视为不同的数字。
https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#compare-double-double-
https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#compareTo-java.lang.Double-
这对于保持哈希函数的一致性也很重要。
不要使用内置的 Java 相等运算符==
即使对于原始双精度值也是如此。正如 JavaDocs 中所述compareTo
方法,相等失败NaN
。 (这个 StackOverflow 问题还有更多信息:为什么Java的Double.compare(double, double)是这样实现的?)
最后一点 - 这不适用于上面的示例,因为使用了原始双精度值,但是如果您使用Double
对象,记得检查null
在尝试将它们传递到任何 Double 比较函数之前。