[英]Little Confusion Over Hashing
考虑下面的代码:
public class CarEqualsTestAgain {
String model;
public CarEqualsTestAgain(String x) {
this.model=x;
}
@Override
public int hashCode(){ //bad hashcode
System.out.println("__hash__");
return 1;
}
@Override
public boolean equals(Object o){
System.out.println("In equals");
if((o instanceof CarEqualsTestAgain) && ((CarEqualsTestAgain)o).model==this.model){
return true;
}
else
return false;
}
public static void main(String[] args) {
Map map=new HashMap();
CarEqualsTestAgain car1=new CarEqualsTestAgain("8");
map.put(car1, "Red");
System.out.println("Key1 : "+map.get(car1)); //Line 1
CarEqualsTestAgain car2=new CarEqualsTestAgain("8");
System.out.println("Key2 : "+map.get(car2)); //Line 2
CarEqualsTestAgain car3=car1;
System.out.println("Key3 : "+map.get(car3)); //Line 3
CarEqualsTestAgain car4=new CarEqualsTestAgain("9");
map.put(car4, "Red");
System.out.println("Key4 : "+map.get(car4)); //Line 4
CarEqualsTestAgain car5=new CarEqualsTestAgain("10");
map.put(car5, "Red");
System.out.println("Key5 : "+map.get(car5)); //Line 5
CarEqualsTestAgain car6=new CarEqualsTestAgain("8");
map.put(car6, "Green");
System.out.println("Key6 : "+map.get(car6)); //Line 6
key=(String)map.get(car1);
System.out.println("Key1 : "+key); //Line 7
}
}
将输出打印为:
__hash__
__hash__
Key1 : Red
__hash__
In equals
Key2 : Red
__hash__
Key3 : Red
__hash__
In equals
__hash__
Key4 : Red
__hash__
In equals
In equals
__hash__
Key5 : Red
__hash__
In equals
In equals
In equals
__hash__
In equals
In equals
In equals
Key6 : Red
__hash__
In equals
In equals
Key1 : Green
我的问题是:
1)创建每个对象时,JVM计算其哈希码并将其放入存储桶中,或者当调用Hashmap put()方法时,只有JVM使用键Object来计算哈希码?
2)put()和get()调用哈希码和equals方法。 因此,put()方法将根据否正确调用覆盖的equals()。 在第1,4,5,6行的输出中看到存储桶中的对象数量。 但是对于get()方法,它是不一样的。 对于第1行,get()不调用equal(),第2行,第3、4、5行不调用,第6行。 7号线不是为什么?
3)equals(Object o)方法比较传递的对象,即所有对象都驻留在具有给定哈希码的存储桶中的Object o。 那么,为什么它在发现一个早期时就不停止共同映射。 例如-在存储区1928中说car1 car4 car5驻留,因此,当car6调用get()并调用equals()时,如果car6与car1比较并且发现相等,则它应停止比较,但将比较3次。 为什么?
当创建每个对象时,JVM计算其哈希码并将其放入存储桶中,或者当调用Hashmap put()方法时,只有JVM使用键Object来计算哈希码?
它仅在需要时调用hashCode()
-在这种情况下,当您调用put()
或get()
。
对于第1行,get()不调用equal(),第2行,第3、4、5行不调用,第6行。 7号线不是为什么?
您对自己的诊断感到困惑。 这个电话:
System.out.println("Key1 : "+map.get(car1));
等效于:
Object tmp = map.get(car1);
System.out.println("Key1 : " + tmp);
因此, 在打印Key1
之前,将调用equals
。 为了更容易理解,您应该将诊断更改为:
System.out.println("Test 1");
CarEqualsTestAgain car1 = new CarEqualsTestAgain("8");
System.out.println("Created car");
map.put(car1, "Red");
System.out.println("Added car to map");
Object tmp = map.get(car1);
System.out.println("Result of get: " + tmp);
这样可以更清楚地了解何时发生的情况。 通常, put()
和get()
需要:
hashCode()
equals()
,直到它用尽匹配项或找到一个相等的对象 3)equals(Object o)方法比较传递的对象,即所有对象都驻留在具有给定哈希码的存储桶中的Object o。 那么,为什么它在发现一个早期时就不停止共同映射。 例如-在存储区1928中说car1 car4 car5驻留,因此,当car6调用get()并调用equals()时,如果car6与car1比较并且发现相等,则它应停止比较,但将比较3次。 为什么?
您假设它首先与car1
比较。 哈希映射实际上是无序的-无法保证将比较具有相同哈希码的候选排序。但是,当找到匹配项时, 它将停止。 如果您将哈希码更改为更明智,则很有可能只需要检查一项即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.