object == object,不比较参考

时间:2018-06-21 14:21:43

标签: java object equals hashcode

我已经覆盖了哈希码,并且等于找到具有相同startDate和closeingDate的值。我正在为重复的对象得到类似的哈希码。当等同于这些对象时,我得到的是布尔值“ false”。在我的理解中,即使引用相同,object == object也会比较对象的引用;代码返回假。能否请您帮助我了解问题所在。我在下面发布了我的代码:

哈希码和等于方法

public int hashCode() {
    final int prime = 31; 
    int result = 1;
    result = prime * result + ((this.startDate == null) ? 0 : this.startDate.getDate());
    result = prime * result + ((this.closingDate == null) ? 0 : this.closingDate.getDate());
    return result;
}

public boolean equals(Object customer) {
    if(customer == null || customer.getClass()!= this.getClass())
        return false;

    return this==customer;
}

Main.java

public class HashQuestion {
    public static void main(String[]args) {
        Map<Integer, Customer> custMap = new HashMap<Integer, Customer>();
        custMap.put(1, createCustomer(1, new Date()));
        custMap.put(2, createCustomer(2, new Date()));
        custMap.put(3, createCustomer(3, new Date()));
        Customer checkCustomer = createCustomer(1, new Date());
        for (Customer cust : custMap.values()) {

            if (cust.equals(checkCustomer)) {
                System.out.println("Duplicate No: "+cust.getCustId()+ ", Start date: " + 
                        cust.getStartDate().toString() + " End date: " +cust.getClosingDate().toString());
            }
            else
                System.out.println("No: "+cust.getCustId()+ ", Start date: " + 
                    cust.getStartDate().toString() + " End date: " +cust.getClosingDate().toString());
        } 
    }

    @SuppressWarnings("deprecation")
    static Customer createCustomer(int number, Date date) {
        Date closeDate = new Date(); 
        Date startDate = new Date(); 
        closeDate.setDate(date.getDate() + number);
        startDate.setDate(date.getDate() - number);
        return new Customer(number, number+1, startDate, closeDate);
    }
}

输出:

No: 1, Start date: Wed Jun 20 19:42:46 IST 2018 End date: Fri Jun 22 19:42:46 IST 2018
No: 2, Start date: Tue Jun 19 19:42:46 IST 2018 End date: Sat Jun 23 19:42:46 IST 2018
No: 3, Start date: Mon Jun 18 19:42:46 IST 2018 End date: Sun Jun 24 19:42:46 IST 2018

checkCustomer对象参考:Customer @ 643

对象引用(在地图中):[Customer @ 643,Customer @ 625,Customer @ 607]

此处object1与checkCustomer obj具有相同的引用。但是obj == checkCustomer,返回false。

5 个答案:

答案 0 :(得分:2)

从此更改:

Map<Integer, Customer> custMap = new HashMap<Integer, Customer>();
custMap.put(1, createCustomer(1, new Date()));
custMap.put(2, createCustomer(2, new Date()));
custMap.put(3, createCustomer(3, new Date()));
Customer checkCustomer = createCustomer(1, new Date()); //This is a different reference

对此:

Map<Integer, Customer> custMap = new HashMap<Integer, Customer>();
Customer checkCustomer = createCustomer(1, new Date());
custMap.put(1, checkCustomer); //Now this is the same reference
custMap.put(2, createCustomer(2, new Date()));
custMap.put(3, createCustomer(3, new Date()));

您要创建4个不同的客户,这将创建3个。

答案 1 :(得分:1)

如果创建一个NEW对象(使用“ new”),则对象在堆中将始终具有不同的地址,因此,如果将它们进行比较,则==将始终返回false。

例如

Integer i1 = new Integer(1);
Integer i2 = new Integer(1);

i1.equals(i2) --> true
i1 == i2 --> false

在最后一行的equals方法中,进行引用比较(==),您不应该在对象(仅基元和枚举)中进行此操作。如果您使用的是IDE(例如eclipse),则可以使用标识对象实例的字段来生成equals和hashcode方法。

答案 2 :(得分:0)

您正在通过创建两个不同的对象

return new Customer(number, number+1, startDate, closeDate);

因此比较必须为假。如果要比较对象的属性,则必须在equals方法中实现该对象。

它应该看起来像这样:

public boolean equals(Object customer) {
    if(customer == null || customer.getClass()!= this.getClass())
        return false;

    return this.getCustId()==customer.getCustId();
}

答案 3 :(得分:0)

因此,让我将答案分为两部分:

(i)对象引用如何评估为相同----  java.lang.Object提供了toString方法的实现, 例如,它返回的字符串是类名,后跟“ at”符号(@)和哈希码的无符号十六进制表示形式。在你的情况下 checkCustomer对象参考:Customer @ 643 对象引用(在地图中):[Customer @ 643,Customer @ 625,Customer @ 607]

地图和检查引用中的第一个元素是完全不同的对象,但是toString()方法将它们计算为相同的原因是由于哈希冲突,而您的自定义hashCode()方法对此有所贡献,

public int hashCode() {
    final int prime = 31; 
    int result = 1;
    result = prime * result + ((this.startDate == null) ? 0 : this.startDate.getDate());
    result = prime * result + ((this.closingDate == null) ? 0 : this.closingDate.getDate());
    return result;
}

这完全没问题,因为没有哈希函数就没有冲突

2)即使引用相同,为什么equals(Object o)实现未返回true ---

让我们检查您的equals方法:

public boolean equals(Object customer) {
    if(customer == null || customer.getClass()!= this.getClass())
        return false;

    return this==customer;
}

请注意,“ ==”运算符将检查两个引用是否指向同一对象。在您的情况下,它没有返回false。

PS:根据经验,请考虑重写toString()方法。在EffectiveJava Second editon中检查论文Item10。

答案 4 :(得分:0)

根据我对此问题的分析,“ ==”比较内存地址,而不是对象引用。以下stackoverflow问题有助于我理解这一点:

What is the difference between == vs equals() in Java?

Memory address of variables in Java

让我知道理解是否错误

谢谢大家