简体   繁体   English

为Double列表覆盖equals()和hashCode()的问题

[英]Problem with overriding equals() and hashCode() for a List of Double

I have a class as follows: 我的课如下:

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

Now, I want to write unit tests and compare this class with another one merely to check equality. 现在,我想编写单元测试并将该类与另一个类进行比较,以仅检查是否相等。 However, I want to allow some room for error so that even if the Doubles are close with respect to some epsilon they're considered equal. 但是,我想允许有一些错误的余地,以便即使Doubles在某些epsilon上接近的,它们也被认为是相等的。 Now, if I override the equals() method NetBeans and Sonar prompt me to override the hashCode() method as well which doesn't make any sense. 现在,如果我重写equals()方法,NetBeans和Sonar会提示我也重写hashCode()方法,这没有任何意义。 The reason is that it's not feasible to simply implement a hashCode() method that outputs the same hash code value for CLOSE lists. 原因是,简单地实现为CLOSE列表输出相同的哈希码值的hashCode()方法是不可行的。

My question is this: 我的问题是这样的:

Should I continue with overriding the equals() method and just override hashCode() for the sake of passing Sonar check? 我是否应该继续重写equals()方法并仅重写hashCode()以便通过声纳检查? (A dummy implementation for hashCode()) (hashCode()的虚拟实现)

OR 要么

Should I just implement this method to check closeness in my unit tests and not in the actual source code? 我应该只在单元测试中而不是在实际源代码中实施这种方法来检查紧密性吗?

This looks like an XY problem. 这看起来像XY问题。

You are entangled in a non-trivial transitivity issue associated with overriding equals() due to your business rule ( "if the Doubles are close with respect to some epsilon..." ), as pointed out in a comment to the OP. 正如您对OP的评论所指出的那样,由于您的业务规则( “如果Doubles相对于某些epsilon是紧密的……” ),您陷入了与覆盖equals()相关的非平凡的传递性问题。

In fact it is impossible for you to meaningfully implement an equals() method for that rule, because transitivity (" if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true ") cannot be guaranteed. 实际上,您不可能为该规则有意义地实现equals()方法,因为传递性(“ 如果x.equals(y)返回true而y.equals(z)返回true,则x.equals(z)应该返回true ”)不能得到保证。 You might have three Data objects, d1, d2 and d3, where d2 was equal (ie close enough) to both d1 and d3, but d1 was not equal (ie not close enough) to d3. 您可能有三个Data对象d1,d2和d3,其中d2与d1和d3相等(即足够接近),但d1与d3不相等(即不够接近)。

There is nothing wrong with the rules Java imposes when testing for equality, and there is nothing wrong with your specific condition for determining the equality of your Data instances either. Java在进行相等性测试时所强加的规则没有错,并且确定Data实例的相等性的特定条件也没有错。 It's just that they are incompatible. 只是它们不兼容。

But while there are a bunch of rules you should definitely follow if you go down the equals() path, I don't see anything in your question that indicates you have to override anything. 但是,尽管有很多规则,但 如果遵循 equals()路径, 绝对应该遵循 ,但我在问题中看不到任何内容表明您必须重写任何内容。 So don't go there. 所以不要去那里。

Why not just create a new method public boolean sameAs(Object other) in the Data class? 为什么不只在Data类中创建一个新的方法public boolean sameAs(Object other) It can check for equality based on your rule(s), and your unit tests can call that method. 它可以根据您的规则检查是否相等,并且单元测试可以调用该方法。 Then you have no need or obligation to implement equals() and hashCode() at all. 然后,您完全没有必要或义务实现equals()hashCode()

(Updated on 9/12/19 to clarify why equals() cannot be implemented.) (于19/12/19更新,以阐明为什么equals()无法实现。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM