“是怎么回事?”;“相同”;是为Java对象定义的吗?

“是怎么回事?”;“相同”;是为Java对象定义的吗?,java,equality,Java,Equality,我想将自定义类型的对象添加到集合中。我有几个是相同的,也就是说,它们的公共变量值相同 我不希望一个“相同”对象的多个实例被添加到集合中,但每次创建一个新对象时,它总是被添加 这是因为类对象的equals方法在对象上实现了最有区别的等价关系:“对于任何非空引用值x和y,当且仅当x和y引用同一对象时(x==y的值为true),此方法才返回true。” 我是否可以重写此对象的equals方法以进行不同的定义 谢谢大家问题解决了 java对象的相同性是通过重写java对象的equals()方法定义的 您

我想将自定义类型的对象添加到集合中。我有几个是相同的,也就是说,它们的公共变量值相同

我不希望一个“相同”对象的多个实例被添加到集合中,但每次创建一个新对象时,它总是被添加

这是因为类对象的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);