【问题标题】:Java compare two sets filled with different instances of same object that satisfy equals()Java比较两个集合,这些集合填充了满足equals()的相同对象的不同实例
【发布时间】:2019-07-21 05:05:03
【问题描述】:

我创建了一个名为 Coordinate 的类,如下所示:

public class Coordinate {
    public int x;
    public int y;

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

    @Override
    public boolean equals(Object obj) {
        Coordinate coordinate = (Coordinate)obj;
        return (coordinate.x == this.x && coordinate.y == this.y);
    }
}

我有两个集合(A 和 B),用 Coordinate 类的实例填充。我想测试我的两个集合是否包含满足 .equals() 的坐标实例。例如:

Coordinate a = new Coordinate(2, 2);
Coordinate b = new Coordinate(2, 2);

A.add(a);
B.add(b);

尽管 a.equals(b) 和 b.equals(a) 的计算结果都为真,但 a 和 b 是不同的实例(因此分配到不同的内存位置),因此比较集合 A 和我遇到的 B 会将它们评估为不同的集合。

有没有办法根据集合的内容是否满足 .equals() 来评估集合是否相等?

【问题讨论】:

    标签: java equals hashset


    【解决方案1】:

    如果您的Sets 是HashSets,您忘记在Coordinate 类中覆盖hashCode()hashCode() 的合约要求如果a.equals(b) 为真,a.hashCode() == b.hashCode() 也必须为真。

    正确覆盖hashCode() 将导致A.equals(B) 返回true,因为equals for Sets 在以下情况下返回true:

    这两个集合的大小相同,并且指定集合的​​每个成员都包含在这个集合中(或者等效地,这个集合的每个成员都包含在指定集合中)。

    一种可能的实现方式:

    @Override
    public int hashCode()
    {
        return Objects.hash(x,y);
    }
    

    【讨论】:

    • 虽然实现hashCode() 是有意义的,但我认为HashSet 有点在Set.equals() 的合同旁边——它不需要哈希码来匹配。对于不一致的测试,尝试Set<Coordinate> A = new TreeSet<>(); Set<Coordinate> B = new HashSet<>();A.equals(B) 返回true,而B.equals(A) 返回false
    • @ernest_k 在Object 类中定义的hashCode 的基本合约要求它匹配equals 的实现。如果您遵守该合同,HashSets 将正常运行。
    • 同意这一点,毫无疑问。但我只是认为HashSet 在这里的Set 实现中很奇怪。 ——诚然,我在吹毛求疵……
    【解决方案2】:

    生成 hashCode 和 equals 方法

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Coordinate other = (Coordinate) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-08
      • 2013-02-12
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多