根据我所读到的,
使用一个对象作为hashMap的关键,它必须提供正确的 覆盖和实施 等于 和 hashCode 方法。 HashMap get(Key k)方法在键上调用hashCode方法 对象并将返回的 hashValue 应用于其自己的静态哈希 函数找到一个桶位置(支持数组)键和 值以名为Entry(Map.Entry)的嵌套类的形式存储。 HashMap的内部哈希方法可以防止质量差的哈希值 功能
为了测试这些合同,我编写了一个bean类,其中 等于 和 hashCode 的错误但合法的实现方法。
班级:
public class HashVO {
private String studentName;
private int age;
private boolean isAdult;
public HashVO(String studentName, int age, boolean isAdult) {
super();
this.studentName = studentName;
this.age = age;
this.isAdult = isAdult;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isAdult() {
return isAdult;
}
public void setAdult(boolean isAdult) {
this.isAdult = isAdult;
}
@Override
public String toString() {
return studentName + " : " + age + " : " + isAdult;
}
@Override
public boolean equals(Object obj) {
return false;
}
@Override
public int hashCode() {
return 31;
}
}
在这种情况下,HashMap的哈希方法,
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
每次都应返回相同的值,因为hashcode总是返回31.所以如果将HashVO类的对象用作hashMap的键,那么 get方法应该不起作用,因为它应该转到同一个桶来检索对象和equals方法总是返回false,因此它无法找到关键对象的匹配。
但是当我使用这种方法时,
public static void main(String[] args) {
HashMap<HashVO, String> voMap = new HashMap<HashVO, String>();
HashVO vo = new HashVO("Item1", 25, true);
HashVO vo1 = new HashVO("Item2", 12, false);
HashVO vo2 = new HashVO("Item3", 1, false);
voMap.put(vo, "Item");
voMap.put(vo1, "Item1");
voMap.put(vo2, "Item2");
System.out.println(voMap.get(vo));
System.out.println(voMap.get(vo1));
System.out.println(voMap.get(vo2));
}
输出正确,显示
Item
Item1
Item2
我想了解为什么即使Equals和HashCode方法实现不正确也会出现正确的输出。
答案 0 :(得分:3)
HashMap
有一个小技巧,可以在使用equals
之前比较对象引用。由于您使用相同的对象引用来添加元素并检索它们,HashMap
将正确返回它们。
请参阅Java 7源代码here(Java 8对HashMap
进行了相当大的改进,但它做了类似的事情)
final Entry<K,V> getEntry(Object key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
// HERE. Uses == with the key
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
请注意,这不是文档的一部分,因此请不要依赖它。
答案 1 :(得分:0)
HashMap的工作原理如下:
1)将保存(Key,Value)的表格单元格的索引计算为key.hashCode();
2)HashMap中的键比较equals()或参考比较。
因此,在您的情况下,所有(K,V)对都将作为LinkedList存储在HashMap表的一个单元格中。 你可以从Map获取它们,因为键的引用将等于