一位同事遇到了一个错误,其中HashMap#containsKey用于验证键值对是否存在。指定的键是不同的类型,因此该方法始终返回false。例如(假设地图填充了他想要检索的对象):
Map<String, String> map = new HashMap<String, String>();
Long value = new Long(12);
boolean hasString = map.containsKey(value);
我的问题是:
为什么Map实现强制您放置K类型的键和V类型的值,但containsKey()方法允许您指定任何对象?
Map接口中还有其他方法,例如get()也接受Object类型的参数。
答案 0 :(得分:2)
我认为这是因为Java的Map实现使用.equals()
命令来确定两个对象是否相等,以用于.containsKey()
或.remove()
等方法。并且由于.equals()
与一般对象进行比较(如果你覆盖它,你通常需要在顶部检查if (!(t instanceof T)) { return false; }
但是没有实际规定A和B必须是同一类型A.equals(B)
为真。
以下是一些突出差异的代码。可能没做你期望的事。
import java.util.*;
public class Test {
static class Foo implements Comparable {
public String a;
public boolean equals(Object obj) {
if (obj instanceof Bar) { return a.equals((((Bar) obj).b)); }
return false;
}
public int compareTo(Object o) {
return this.equals(o) ? 0 : -1;
}
}
static class Bar implements Comparable {
public String b;
public boolean equals(Object obj) {
if (obj instanceof Foo) { return b.equals((((Foo) obj).a)); }
return false;
}
public int compareTo(Object o) {
return this.equals(o) ? 0 : -1;
}
}
public static void main(String [] args) {
Map<Foo, Bar> test = new TreeMap<Foo, Bar>();
Foo foo = new Foo();
Bar bar = new Bar();
foo.a = "Hello";
bar.b = "Hello";
System.out.println(foo.equals(bar));
System.out.println(bar.equals(foo));
test.put(foo, bar);
System.out.println(test.containsKey(bar));
System.out.println(test.containsValue(foo));
}
}