我在使用函数containsKey时遇到了一些问题。我写了一个小程序来显示我期望包含密钥的地方给我一个不同的结果:
HashMap<IdentifierInterface, Set<NaturalNumberInterface>> hashMap;
HashMap<StringBuffer, Integer> works;
TryHashmap(){
hashMap = new HashMap<IdentifierInterface, Set<NaturalNumberInterface>>();
works = new HashMap<StringBuffer, Integer>();
}
private void start() {
Identifier iden = new Identifier('a');
NaturalNumber nn = new NaturalNumber('8');
Set<NaturalNumberInterface> set = new Set<NaturalNumberInterface>();
set.insert(nn);
hashMap.put(iden, set);
System.out.println(hashMap.containsKey(iden));
Identifier newIden = new Identifier('a');
System.out.println(hashMap.containsKey(newIden)); //TODO why is this not true?
iden.init('g');
System.out.println(hashMap.containsKey(iden));
}
public static void main(String[] argv) {
new TryHashmap().start();
}
Identifier 类的构造函数如下所示,init() 类似,但它将删除之前标识符中的任何内容。
Identifier(char c){
iden = new StringBuffer();
iden.append(c);
}
我使用标识符作为键将一些东西放入哈希图中,但是当我尝试使用具有不同名称但内容相同的标识符时,containsKey 函数在我期望 true 的地方返回 false。(输出打印为 true假真)
提前感谢!
为标识符对象实现equals()
和hashCode()
。 需要hashCode
才能找到相关的存储桶,并且需要equals
来处理哈希时的冲突。
延伸阅读
HashMap.class
中containsKey
的方法
/**
* Returns <tt>true</tt> if this map contains a mapping for the
* specified key.
*
* @param key The key whose presence in this map is to be tested
* @return <tt>true</tt> if this map contains a mapping for the specified
* key.
*/
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
方法getEntry
HashMap.class
/**
* Returns the entry associated with the specified key in the
* HashMap. Returns null if the HashMap contains no mapping
* for the key.
*/
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}
该方法getEntry
告诉我们,只有当对象a
与对象具有相同的hashCode()
时,结果才会true
b
并a.equals(b)