“是怎么回事?”;“相同”;是为Java对象定义的吗?
我想将自定义类型的对象添加到集合中。我有几个是相同的,也就是说,它们的公共变量值相同 我不希望一个“相同”对象的多个实例被添加到集合中,但每次创建一个新对象时,它总是被添加 这是因为类对象的equals方法在对象上实现了最有区别的等价关系:“对于任何非空引用值x和y,当且仅当x和y引用同一对象时(x==y的值为true),此方法才返回true。” 我是否可以重写此对象的equals方法以进行不同的定义 谢谢大家问题解决了 java对象的相同性是通过重写java对象的equals()方法定义的“是怎么回事?”;“相同”;是为Java对象定义的吗?,java,equality,Java,Equality,我想将自定义类型的对象添加到集合中。我有几个是相同的,也就是说,它们的公共变量值相同 我不希望一个“相同”对象的多个实例被添加到集合中,但每次创建一个新对象时,它总是被添加 这是因为类对象的equals方法在对象上实现了最有区别的等价关系:“对于任何非空引用值x和y,当且仅当x和y引用同一对象时(x==y的值为true),此方法才返回true。” 我是否可以重写此对象的equals方法以进行不同的定义 谢谢大家问题解决了 java对象的相同性是通过重写java对象的equals()方法定义的 您
您需要重写<代码>均衡器()>代码> <强>和<代码> HASCODE()方法,以告诉HasSead您认为相等。
如果您使用的是树集,那么应该实现
Comparable
。您肯定应该重写equals
和hashCode
,因为它们是Java用来定义对象相等性的方法。默认情况下,所有对象都是不同的。
有关实现的详细信息,请参阅Joshua Bloch的《高效Java》一书 正如SLaks所说,您应该重写equals()
和hashCode()
方法。重写equals()
时,将考虑这些值,例如:
public class MyObject
public int x;
public int y;
public boolean equals(Object obj) {
return (obj instance of MyObject) && (obj.x==x && obj.y==y);
}
public int hashCode() {
return (x+y)*31;
}
}您完全可以重写equals()来比较类中的重要字段。然而,有一些重要的事情需要记住。发件人:
-如果重写equals,则必须重写hashCode
-哈希代码必须为相等的对象生成相等的值
-equals和hashCode必须依赖于同一组“有效”字段。在这两种方法中必须使用相同的字段集。您不必使用所有字段。例如,equals和hashCode中很可能会忽略依赖于其他字段的计算字段
这基本上是因为集合数据结构被实现为散列集合;它需要hashCode()将对象放置在基础数组中并在以后找到它,还需要equals()来解决哈希冲突(即,多个对象哈希到相同的值)
下面是关于实现hashCode()的一个很好的指南:
[编辑]
我想附和kostja的建议,阅读Josh Bloch关于这个主题的章节。这是一本了不起的书。添加Set的功能,检查hashcode()方法&如果它返回true,那么它将调用equal()。每个对象都有不同的内存位置&对象类的equals()只是比较内存位置位以检查是否相等。因此,每个对象都会被添加
要想实现这一点,您必须向类中添加hashCode()和equals()方法,这些方法将比较类特定的属性,根据您的想法,这些属性会创建相同的含义。正如SLaks已经指出的,覆盖equals()
和hashCode()
方法肯定是有意义的。为了确保<代码>均衡器()>代码>方法按照您希望的方式运行——在该方法中检查成员变量,即您考虑区分两个对象的值是否保持相同的值。< P>关于:
我觉得我的问题是
这两者并不相等,因为它们
不同的物体发生在
具有相同的值
equals
的默认实现执行最严格的(文档称最有区别的)可能形式的相等测试,即测试身份(即两个引用引用引用内存中的同一位置)
这是平等的一种形式,但并不总是最有用的。通常,您要测试的是两个对象具有相同的属性。这是一件非常自然的事情,不值得担心。您应该为自定义类型重写equals
和hashCode
方法
不过要小心,在这里你可能会遇到各种各样的麻烦:例如,如果你的自定义类型有子类型,你可能会遇到其他平等性问题:
class Point {
final int x;
final int y;
public Point(int x, int y) {
this.x= x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (o == this) return true; //If objects equal, is OK
if (o instanceof Point) {
Point that = (Point)o;
return (x == that.x) && y == that.y);
}
return false;
}
}
class ColoredPoint extends Point {
final Color color;
ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color
}
}
Point p1 = new Point(1, 2);
ColoredPoint cp1 = new ColoredPoint(1, 2, Color.BLUE);
ColoredPoint cp1 = new ColoredPoint(1, 2, Color.RED);
目前,p1、cp1和cp2都是相等的。然而,显然cp1和cp2并不相等。您还需要在ColoredPoint中实现一个equals来比较ColoredPoint对象(但这会破坏p1和cp1或cp2之间的相等性)
另外,确保你的对等者有上面的签名。将其定义为公共等于(点)…
,这是一个常见的错误,这是错误的
有关equals和hashCode规则的完整解释,请参阅。谢谢,我将遵循tutes和其他方法。除了覆盖equals和hashCode之外,您还应该避免对象中的公共变量。当对象位于集合中时,用于实现相等的字段也不应更改。为了确保不会发生这种情况,您应该使它们不可变(一旦在构造函数中初始化,它们就永远不会更改)。您不需要检查obj是否为null,(obj instanceof Resource)对于obj==null将始终为false。您还需要hashCode()
。我的示例的目的是显示equals(),而不是hashCode(),但我还是添加了一个简单的hashCode(),因为你问了。给出的所有答案都是正确的,但有些答案比其他答案更正确。顺便说一下,我应该提到集合不使用equals方法来检查内容相等性,而是使用hashCode方法。因此,调用yourSet.Contains(someObject)检查集合中包含的哈希代码,而不是通过集合对每个项调用equals。这就是hashCode和equals应该一起被重写并且应该依赖于同一个interna的原因之一(实际上是主要原因)
class Point {
final int x;
final int y;
public Point(int x, int y) {
this.x= x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (o == this) return true; //If objects equal, is OK
if (o instanceof Point) {
Point that = (Point)o;
return (x == that.x) && y == that.y);
}
return false;
}
}
class ColoredPoint extends Point {
final Color color;
ColoredPoint(int x, int y, Color color) {
super(x, y);
this.color = color
}
}
Point p1 = new Point(1, 2);
ColoredPoint cp1 = new ColoredPoint(1, 2, Color.BLUE);
ColoredPoint cp1 = new ColoredPoint(1, 2, Color.RED);