【问题标题】:How to correct hashCode() methos to correctly use HashSet collection如何更正 hashCode() 方法以正确使用 HashSet 集合
【发布时间】:2017-12-14 11:12:44
【问题描述】:

为了确保我们的 equals 和 hashcode() 得到很好的实现,我们必须确保以下规则

  • 自反性
  • 对称
  • 传递性
  • 一致性
  • 非无效性

但是我的以下实现违反了规则一致性(如果我修改它的字段,x 永远不会等于它自己)所以我必须做些什么才能使这个测试正确运行?

public class TestHashCode {

public class Point {

    public int x;
    public int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int hashCode() {
        int hash = 3;
        hash = 97 * hash + this.x;
        hash = 97 * hash + this.y;
        return hash;
    }

    public boolean equals(Object obj) {
        // generated code by netbeans IDE
    }

}

@Test
public void testEquals() {
    Point x = new Point(1, 1);
    Set<Point> pointsAsSet = new HashSet<>();
    pointsAsSet.add(x);
    x.x = 3 ;
    Assert.assertTrue(pointsAsSet.contains(x));
}

}

【问题讨论】:

    标签: java hashset hashcode


    【解决方案1】:

    您不能改变HashSet(参与equalshashCode 的实现)成员的属性并期望它能够工作。

    要么不要改变这些属性,要么在改变之前从HashSet 中删除元素,然后再重新添加:

    Point x = new Point(1, 1);
    Set<Point> pointsAsSet = new HashSet<>();
    pointsAsSet.add(x);
    ...
    pointsAsSet.remove(x);
    x.x = 3 ;
    pointsAsSet.add(x);
    ...
    Assert.assertTrue(pointsAsSet.contains(x));
    

    作为替代方案,如果您在 Point 类中有一些独特的不可变属性,则可以将其用作 HashMap 中的键(例如 HashMap&lt;Integer,Point&gt;),然后您就不需要您的 @ 987654329@ 类覆盖equalshashCode

    【讨论】:

    • 没错,可能会提议public final int x; public final int y; - 不可变对象,允许共享。
    猜你喜欢
    • 2014-02-05
    • 1970-01-01
    • 2013-03-29
    • 2020-07-03
    • 1970-01-01
    • 2019-11-02
    • 2020-04-01
    • 2012-08-06
    • 1970-01-01
    相关资源
    最近更新 更多