如何比较两个java对象

如何比较两个java对象,java,object,compare,Java,Object,Compare,我有两个从同一个类实例化的java对象 MyClass myClass1 = new MyClass(); MyClass myClass2 = new MyClass(); 如果我将它们的两个属性设置为完全相同的值,然后验证它们是否相同 if(myClass1 == myClass2){ // objects match ... } if(myClass1.equals(myClass2)){ // objects match ... } 但是,这两种方法都不

我有两个从同一个类实例化的java对象

MyClass myClass1 = new MyClass();
MyClass myClass2 = new MyClass();
如果我将它们的两个属性设置为完全相同的值,然后验证它们是否相同

if(myClass1 == myClass2){
   // objects match
   ...

}

if(myClass1.equals(myClass2)){
   // objects match
   ...

}
但是,这两种方法都不会返回真实值。我已经检查了每个的属性,并且它们匹配


如何比较这两个对象以验证它们是否相同?

您必须从类对象正确重写方法equals()

编辑:我认为我的第一个回答被误解了,可能是因为我不太准确。所以我决定添加更多的解释

为什么必须重写equals()?好吧,因为这是由开发人员来决定两个对象相等意味着什么。对于大多数情况,引用相等是不够的

例如,假设您有一个HashMap,其键的类型为Person。每个人都有姓名和地址。现在,您希望使用该键查找详细的bean。问题是,您通常无法创建引用与映射中引用相同的实例。您要做的是创建类Person的另一个实例。显然,运算符==在这里不起作用,您必须使用equals()

但现在,我们来讨论另一个问题。假设您的集合非常大,您希望执行搜索。朴素的实现将使用equals()将键对象与映射中的每个实例进行比较。然而,这将是非常广泛的。下面是hashCode()。正如其他人指出的,hashcode是一个不必唯一的数字。重要的要求是,每当equals()为两个对象提供true时,hashCode()必须为这两个对象返回相同的值。相反的含义不成立,这是一件好事,因为hashcode将我们的密钥分成了不同的存储桶。我们在单个bucket中有少量的类Person实例。当我们执行搜索时,算法可以立即跳转到正确的bucket,并且现在只对每个实例执行equals。因此,hashCode()的实现必须尽可能均匀地将对象分布在各个存储桶中

还有一点。有些集合需要在用作键的类中正确实现hashCode()方法,而不仅仅是出于性能原因。例如:HashSet和LinkedHashSet。如果它们不重写hashCode(),则默认对象 HASCODE()方法将允许多个对象,您可以“有意义地考虑”。 “相等”添加到“不允许重复”集合中

使用hashCode()的某些集合

  • 哈希集
  • 链接数据集
  • 哈希映射
看看apache commons中的这两个类,它们将使您能够轻松地实现equals()和hashCode()


您需要在
MyClass
中提供自己的
equals()
实现

@Override
public boolean equals(Object other) {
    if (!(other instanceof MyClass)) {
        return false;
    }

    MyClass that = (MyClass) other;

    // Custom equality check here.
    return this.field1.equals(that.field1)
        && this.field2.equals(that.field2);
}
如果您的对象有可能在哈希表中使用,您还应该重写
hashCode()
。一种方法是将对象字段的哈希代码与如下内容组合:

@Override
public int hashCode() {
    int hashCode = 1;

    hashCode = hashCode * 37 + this.field1.hashCode();
    hashCode = hashCode * 37 + this.field2.hashCode();

    return hashCode;
}

有关实现哈希函数的更多详细信息,请参阅。

您需要覆盖
equals
hashCode

equals
将根据您需要的属性比较对象是否相等,并且
hashCode
是必需的,以便在
集合中正确使用您的对象
映射

1)==在这种情况下评估引用相等性

2) 我对equals不太确定,但是为什么不简单地重写compare方法并将其植入MyClass中呢?

您需要在
MyClass中实现equals()方法

==
不起作用的原因是检查它们是否引用了相同的实例。因为您为每个都添加了
new
,所以每个都是不同的实例

equals()
不起作用的原因是您自己还没有实现它。我相信它的默认行为与
=
是一样的


请注意,如果要实现
equals()
,您还应该实现
hashcode()
,因为很多java.util集合都希望这样

@Aubin通常,在哈希代码生成中使用素数。如果我没有弄错的话,它减少了在生成的哈希上发生冲突的可能性。至于为什么要用37,我想这只是一个流行的选择,我不知道为什么要用37而不是13。谢谢大家,真的。每个人都让我走上了正确的道路,但我只能接受其中一条是正确的。@John Your equals也可以检查
other==this
,虽然这不是必需的,但它会在不验证每个字段的情况下返回true。@ArthurEirich我现在看到了。不,你说得对,我已经更新了我的答案以匹配链接。@Aubin我认为37来自蒙特卡罗测试,对字符串的相同测试表明31也是可以接受的,并且它不太复杂,因此31用于java字符串哈希代码。数据结构和算法分析中的图5.45显示了这一点。一个清晰的数字可以在很好的解释中找到。简明扼要。