我试图了解 Java 中的实现 HashTables。下面是我的代码:
Hashtable<Integer, String> hTab = new Hashtable<Integer, String>();
hTab.put(1, "A");
hTab.put(1, "B");
hTab.put(2, "C");
hTab.put(3, "D");
Iterator<Map.Entry<Integer, String>> itr = hTab.entrySet().iterator();
Entry<Integer, String> entry;
while(itr.hasNext()){
entry = itr.next();
System.out.println(entry.getValue());
}
当我运行它时,我得到以下输出:D C B
这意味着 Key = 1 发生了冲突;并根据实施:
“每当哈希表中发生冲突时,都会在与特定存储桶对应的linkedList中创建一个新节点,并将EntrySet(Key,Value)对存储为列表中的节点,新值插入到列表的开头对于特定的桶”。我完全同意这个实施。
但如果这是真的,那么当我尝试从 hashTable 中检索条目集时,“A”去了哪里?
同样,我尝试使用下面的代码通过实现我自己的 HashCode 和 equals 方法来理解这一点。令人惊讶的是,这非常完美,并且符合 HashTable 实现。下面是我的代码:
public class Hash {
private int key;
public Hash(int key){
this.key = key;
}
public int hashCode(){
return key;
}
public boolean equals(Hash o){
return this.key == o.key;
}
}
public class HashTable1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Hashtable<Hash, String> hTab = new Hashtable<Hash, String>();
hTab.put(new Hash(1), "A");
hTab.put(new Hash(1), "B");
hTab.put(new Hash(2), "C");
hTab.put(new Hash(3), "D");
Iterator<Map.Entry<Hash, String>> itr = hTab.entrySet().iterator();
Entry<Hash, String> entry;
while(itr.hasNext()){
entry = itr.next();
System.out.println(entry.getValue());
}
}
}
输出:D C B A
这是完美的。我无法理解 Java 中 HashTable 行为的这种歧义。
更新
@garrytan 和@Brian:感谢您的回复。但我还有一个小小的疑问。
在我的第二个代码中,它工作正常。我创建了两个对象,它们是新键,因为它们是 2 个对象,在这种情况下不会发生键冲突,并且工作正常。我同意你的解释。但是,如果在第一组代码中我使用“new Integer(1)”而不是简单的“1”,它仍然不起作用,尽管现在我正在创建 2 个对象并且它们应该不同。我通过写下面的简单行进行了交叉检查:
Integer int1 = new Integer(1);
Integer int2 = new Integer(1);
System.out.println(int1 == int2);
这给出了“错误”。这意味着现在,密钥冲突应该已经解决了。但它仍然不起作用。为什么是这样?