如何用 Java 编写相等方法
考虑将相等方法添加到以下简单点的类中:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
虽然您确实应该在实现
equals()
时实现hashCode()
,但这不会导致您的问题。这不是您正在寻找的
equals()
方法。 equals 方法必须始终具有以下签名:“public boolean equals(Object object)”。这是一些代码。Apache EqualsBuilder 类 是对于 equals 实现很有用。该链接是旧版本,但仍然适用。
如果您喜欢 Apache EqualsBuilder,您可能会喜欢 Apache HashCodeBuilder 类 也是如此。
编辑:更新了标准快捷方式的 equals 方法示例。
While it is true that you should implement
hashCode()
when you implementequals()
, 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.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.
每当您重写
equals()
时,都必须实现hashCode()
。两者一起工作,并且必须始终给出一致的结果。如果不这样做,就会产生您观察到的错误行为。这在 Effective Java 2nd Edition,第 9 项:在覆盖 equals 时始终覆盖 hashCode。
You must implement
hashCode()
whenever you overrideequals()
. 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.
通过覆盖哈希码可以很好地工作!
永远记住:在覆盖 equals 时覆盖 hashCode。
这是我的 hashCode 实现。
Works well by overriding hashcode !
Always remember : override hashCode when you override equals.
This is my implementations of hashCode.
根据
equals()
上的约定,您还需要实现hashCode()
。来自 JavaDoc 上
equals()
:As per contract on
equals()
you need to implementhashCode()
as well.From the JavaDoc on
equals()
:除了其他答案:
如果您使用 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.
覆盖
equals
时,您还必须覆盖hashCode
(特别是,如果您要使用HashSet
或HashMap
>...)。一个合适的(尽管不太聪明)实现是:另一点(没有双关语):您实际上并没有重写类
Object
中定义的equals(Object)
方法,而是定义一个新的。正确的方法是:注意,
equals
方法有一个与它相关的相当强大的契约,您需要履行它。When overriding
equals
, you also have to overridehashCode
(in particular, if you are going to useHashSet
orHashMap
...). A suitable (though not to clever) implementation would be:Another point (no pun intended): You are not actually overriding the
equals(Object)
method defined in classObject
, but instead are defining a new one. The correct way would be:Note, that the
equals
method has a pretty strong contract associated with it, which you are to fulfill.