public class Dog {
String name;
public Dog(String name) {
this.name = name;
}
public boolean equals(Object o) {
if ((this == o) && ((Dog) o).name == name) {
return true;
} else {
return false;
}
}
public int hashCode() {
return name.length();
}
}
class Cat {
}
enum Pets {
DOG, CAT, HORSE
}
class MapTest {
public static void main(String[] args) {
Map<Object, Object> m = new HashMap<Object, Object>();
m.put("k1", new Dog("aiko"));
m.put("k2", Pets.DOG);
m.put(Pets.CAT, "CAT Key");
Dog d1 = new Dog("Clover");
m.put(d1, "Dog key");
m.put(new Cat(), "Cat key");
System.out.println(m.get("k1"));
String k2 = "k2";
System.out.println(m.get(k2));
System.out.println(m.get(Pets.CAT));
System.out.println(m.get(d1));
System.out.println(m.get(new Cat()));
// UNABLE TO UNDERSTAND BELOW PART OF CODE
d1.name = "magnolia";
System.out.println(m.get(d1)); // #1 //prints Dog Key
d1.name = "clover";
System.out.println(m.get(new Dog("clover"))); // #2 // prints null
d1.name = "arthur";
System.out.println(m.get(new Dog("clover"))); // #3 // prints null
}
}
我试图理解 kathy 和 berts 的 SCJP6 书中的 hashcode() 实现。虽然我对哈希码实现有基本的了解,但书中的一个场景欺骗了我,我对输出感到困惑。
根据上面的程序,它说:
- 在第一次调用 get() 时,哈希码是 8 (magnolia),它 应该是 6(三叶草),所以检索在步骤 1 失败,我们得到 空。
- 在第二次调用 get() 时,哈希码都是 6,因此步骤 1 成功了。一旦进入正确的存储桶(“名称长度 = 6”) Bucket),调用 equals() 方法,并且由于 Dog 的 equals() 方法比较名称,equals()成功,输出为Dog key。
- 在第三次调用 get() 时,哈希码测试成功,但是 equals() 测试失败,因为 arthur 不等于 clover。
上面三行讨论了名称的长度及其相关的 hashcode() 实现,但是调用 get() 方法时如何比较长度?
最佳答案
equals 实现与文本内容不符。对于不同的对象来说永远不会如此!另外,hashcode
应该有一个大写的 C
hashCode
。此代码的工作原理如下:
import java.util.*;
class MapTest {
static class Dog {
String name;
public Dog(String name) {
this.name = name;
}
public boolean equals(Object o) {
if ((this == o)) {
return true;
} else if (((Dog)o).name.equals(this.name)) {
return true;
} else {
return false;
}
}
public int hashCode() {
return name.length();
}
}
static class Cat {
}
static enum Pets {
DOG, CAT, HORSE
}
public static void main(String[] args) {
Map<Object, Object> m = new HashMap<Object, Object>();
m.put("k1", new Dog("aiko"));
m.put("k2", Pets.DOG);
m.put(Pets.CAT, "CAT Key");
Dog d1 = new Dog("Clover");
m.put(d1, "Dog key");
m.put(new Cat(), "Cat key");
System.out.println(m.get("k1"));
String k2 = "k2";
System.out.println(m.get(k2));
System.out.println(m.get(Pets.CAT));
System.out.println(m.get(d1));
System.out.println(m.get(new Cat()));
// UNABLE TO UNDERSTAND BELOW PART OF CODE
d1.name = "magnolia";
System.out.println(m.get(d1)); // #1
d1.name = "clover";
System.out.println(m.get(new Dog("clover"))); // #2
d1.name = "arthur";
System.out.println(m.get(new Dog("clover"))); // #3
}
}
编辑:并回答“调用 get() 方法时如何比较长度?”:
put
使用 hashCode()
计算将放置值(和键)的存储桶。
get()
将首先查找存储桶。存储桶由 hashCode()
确定,它是名称的长度。如果名称的长度不同,存储桶(希望)会不同,因此 get()
将找不到匹配的条目。这解释了 #1
:相同的对象,但 put 和 get 之间的哈希码发生了变化,因此 get 会在不同的存储桶中查找。
现在,一旦找到合适的存储桶,get()
将查找存储桶中的键,并使用 equals()
进行比较,因为有多个键可以放在同一个桶里。这解释了#3
:相同的存储桶,但对象不是equal()
。 #2
是同一个存储桶,并且对象是 equal()
,因为名称是 equal()
。
关于java - 根据传递的字符串长度实现Hashcode方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30059816/