我已经覆盖了哈希码,并且等于找到具有相同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。
答案 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
让我知道理解是否错误
谢谢大家