【问题标题】:Problem with overriding equals() and hashCode() for a List of Double为 Double 列表覆盖 equals() 和 hashCode() 的问题
【发布时间】:2020-01-13 19:56:11
【问题描述】:

我有一堂课如下:

public class Data{
   int x;
   ArrayList<Double> list;
}

现在,我想编写单元测试并将这个类与另一个类进行比较,只是为了检查是否相等。但是,我想留出一些错误空间,以便即使双打 相对于某个 epsilon 很接近,它们也被认为是相等的。现在,如果我重写 equals() 方法,NetBeans 和 Sonar 提示我也重写 hashCode() 方法,这没有任何意义。原因是简单地实现一个 hashCode() 方法为 CLOSE 列表输出相同的哈希码值是不可行的。

我的问题是这样的:

我是否应该继续覆盖 equals() 方法并只覆盖 hashCode() 以通过声纳检查? (hashCode() 的虚拟实现)

我是否应该只在我的单元测试中而不是在实际源代码中实现此方法来检查接近度?

【问题讨论】:

  • 如果你有一个SetData 会发生什么
  • 当心:这种方法意味着如果 ````a.equals(b)``` 和 b.equals(c),仍然有可能是 !a.equals(c)。也就是说,您刚刚创建了一个不可传递的 equals 版本。
  • 要求如果a.equals(b)a.hashCode() == b.hashCode(),否则哈希集/映射不起作用。您可以通过(例如)return 1 作为您的实现来轻松满足这一点,尽管我并没有声称这是一个很好的哈希算法。但是,如果您从不使用散列集合……!一般来说,我觉得编写糟糕的代码来满足样式检查员在道德上是可憎的,但是这里有一个需要满足的合同。

标签: java unit-testing netbeans sonarqube junit4


【解决方案1】:

这看起来像是一个 XY 问题。

由于您的业务规则(“如果 Doubles 在某些 epsilon 方面接近...”),您陷入了与覆盖 equals() 相关的重要传递性问题中,如在对 OP 的评论中指出。

事实上,您不可能为该规则有意义地实现equals() 方法,因为传递性(“如果 x.equals(y) 返回 true 并且 y.equals(z) 返回 true,则 x .equals(z) 应该返回 true") 不能保证。您可能有三个Data 对象,d1、d2 和 d3,其中 d2 与 d1 和 d3 相等(即足够接近),但 d1 与 d3 不相等(即不够接近)。

Java 在测试相等性时强加的规则没有错,您确定Data 实例相等性的具体条件也没有错。只是它们不兼容。

但是,虽然there are a bunch of rules you should definitely follow 如果 您沿着equals() 路径前进,但我在您的问题中看不到任何表明您必须覆盖任何内容的内容。所以不要去那里。

为什么不在Data 类中创建一个新方法public boolean sameAs(Object other)?它可以根据您的规则检查是否相等,并且您的单元测试可以调用该方法。那么你完全没有必要也没有义务实现equals()hashCode()

(于 2019 年 9 月 12 日更新,以阐明为什么无法实现 equals()。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    相关资源
    最近更新 更多