如何用 Java 编写相等方法

发布于 2025-01-01 15:19:37 字数 996 浏览 1 评论 0原文

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

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

为什么 coll 不包含 p2,即使 p1 被添加到其中,并且 p1 和 p2 是相等的对象?

Consider adding an equality method to the following class of simple points:

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;
    }

    // ...
}

// my definition of equals

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

What's wrong with this method? At first glance, it seems to work OK:

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

However, trouble starts once you start putting points into a collection:

import java.util.HashSet;

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

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

How can it be that coll does not contain p2, even though p1 was added to it, and p1 and p2 are equal objects?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

仙女 2025-01-08 15:19:37

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

这不是您正在寻找的 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 类 是对于 equals 实现很有用。该链接是旧版本,但仍然适用。

如果您喜欢 Apache EqualsBuilder,您可能会喜欢 Apache HashCodeBuilder 类 也是如此。

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

While it is true that you should implement hashCode() when you implement equals(), that is not causing your problem.

That is not the equals() method you are looking for. The equals method must always have the following signature: "public boolean equals(Object object)". Here is some code.

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;
  }
}

The Apache EqualsBuilder class is useful for equals implementations. The link is an older version, but still applicable.

If you liked the Apache EqualsBuilder, you will probably like the Apache HashCodeBuilder class as well.

Edit: updated the equals method example for standard shortcuts.

江挽川 2025-01-08 15:19:37

每当您重写 equals() 时,都必须实现 hashCode()。两者一起工作,并且必须始终给出一致的结果。如果不这样做,就会产生您观察到的错误行为。

这在 Effective Java 2nd Edition,第 9 项:在覆盖 equals 时始终覆盖 hashCode

You must implement hashCode() whenever you override equals(). These two work together, and they must give consistent results at all times. Failing to do so produces just the erroneous behaviour you observed.

This is explained in more detail e.g. in Effective Java 2nd Edition, Item 9: Always override hashCode when you override equals.

葬花如无物 2025-01-08 15:19:37

通过覆盖哈希码可以很好地工作!

永远记住:在覆盖 equals 时覆盖 hashCode。

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

这是我的 hashCode 实现。

Works well by overriding hashcode !

Always remember : override hashCode when you override equals.

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

This is my implementations of hashCode.

夜未央樱花落 2025-01-08 15:19:37

根据 equals() 上的约定,您还需要实现 hashCode()

来自 JavaDoc equals()

请注意,每当重写 hashCode 方法时,通常都需要重写该方法,以维护 hashCode 方法的通用约定,即相等的对象必须具有相等的哈希码。

As per contract on equals() you need to implement hashCode() as well.

From the JavaDoc on equals():

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

恋竹姑娘 2025-01-08 15:19:37

除了其他答案:

如果您使用 Eclipse 作为 IDE,您可以简单地使用“Source”-->; “生成 hashCode() 和 equals() 以获得基本实现。用它做你想做的事。

In addition to the other answers:

If you are using Eclipse as IDE, you can simply use "Source" --> "Generate hashCode() and equals() to get a basic implementation. Do with that what ever you want.

聚集的泪 2025-01-08 15:19:37

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

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

另一点(没有双关语):您实际上并没有重写类 Object 中定义的 equals(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方法有一个与它相关的相当强大的契约,您需要履行它。

When overriding equals, you also have to override hashCode (in particular, if you are going to use HashSet or HashMap...). A suitable (though not to clever) implementation would be:

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

Another point (no pun intended): You are not actually overriding the equals(Object) method defined in class Object, but instead are defining a new one. The correct way would be:

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();
    }
}

Note, that the equals method has a pretty strong contract associated with it, which you are to fulfill.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文