如何在Java中编写一个等式方法

时间:2012-01-31 16:13:45

标签: java equality

考虑将等式方法添加到以下类简单点:

public class Point {

    private final int x;
    private final int y;

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

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    // ...
}

//我对equals的定义

public boolean equals(Point other) {
  return (this.getX() == other.getX() && this.getY() == other.getY());
}

这种方法有什么问题?乍一看,似乎工作正常:

Point p1 = new Point(1, 2);
Point p2 = new Point(1, 2);

Point q = new Point(2, 3);

System.out.println(p1.equals(p2)); // prints true

System.out.println(p1.equals(q)); // prints false

但是,一旦开始将积分放入集合中,麻烦就会开始:

import java.util.HashSet;

HashSet<Point> coll = new HashSet<Point>();
coll.add(p1);

System.out.println(coll.contains(p2)); // prints false

即使p1被添加到它,并且p1和p2是相等的对象,它怎么可能不包含p2?

6 个答案:

答案 0 :(得分:8)

虽然您在实施hashCode()时应该实施equals(),但这不会导致您的问题。

这不是您正在寻找的equals()方法。 equals方法必须始终具有以下签名:“public boolean equals(Object object)”。这是一些代码。

public boolean equals(Object object)
{
  if (object == null)
  {
    return false;
  }

  if (this == object)
  {
    return true;
  }

  if (object instanceof Point)
  {
    Point point = (Point)object;
    ... now do the comparison.
  }
  else
  {
     return false;
  }
}

Apache EqualsBuilder class对于equals实现非常有用。该链接是旧版本,但仍然适用。

如果您喜欢Apache EqualsBuilder,您可能也会喜欢Apache HashCodeBuilder class

编辑更新了标准快捷方式的等于方法示例。

答案 1 :(得分:4)

每当您覆盖hashCode()时,您必须实施equals()。这两者协同工作,必须始终提供一致的结果。如果不这样做,就会产生你观察到的错误行为。

这将更详细地解释,例如在Effective Java 2nd Edition中,第9项:覆盖等于时始终覆盖hashCode。

答案 2 :(得分:2)

通过覆盖哈希码来运行良好!

永远记住:覆盖等于时覆盖hashCode。

@Override public int hashCode() {
        return (41 * (41 + getX()) + getY());
    }

这是我对hashCode的实现。

答案 3 :(得分:1)

根据equals()上的合同,您还需要实施hashCode()

来自equals()上的JavaDoc

  

请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相同的哈希代码。

答案 4 :(得分:1)

除了其他答案:

如果您使用Eclipse作为IDE,则只需使用&#34; Source&#34; - &GT; &#34;生成hashCode()和equals()以获得基本实现。随便做你想做的事。

答案 5 :(得分:0)

覆盖equals时,您还必须覆盖hashCode(特别是,如果您要使用HashSetHashMap ...)。一个合适的(虽然不聪明)实现将是:

int hashCode() {
    return x * 31 + y;
}

另一点(没有双关语):你实际上并没有覆盖类equals(Object)中定义的Object方法,而是定义了一个新方法。正确的方法是:

boolean equals(Object other) {
    if (other == this) return true;
    else if (!(other instanceof Point)) return false;
    else {
        Point p = (Point)other;
        return x == p.getX() && y == p.getY();
    }
}

请注意,equals方法与pretty strong contract相关联,您要完成此操作。