我正在尝试将HashMap与我的类Cell作为关键。但是,在将项目放入HashMap之后,在项目上调用contains将返回false。
public static void main(String args[]) {
HashMap<Cell, String> map = new HashMap<Cell, String>();
map.put(new Cell(0,0), "Bob");
System.out.println(map.containsKey(new Cell(0,0)));
System.out.println(new Cell(0,0).equals(new Cell(0,0)));
}
这打印出false和true,它应该打印true和true,因为根据Map docs containsKey使用.equals()。我做错了什么?
答案 0 :(得分:4)
这很可能是因为您没有实施equals()
和hashCode()
。在Java中,经验法则是如果实现一个,则必须实现另一个。在您的情况下,它是强制性的,因为HashMap
使用它们。
您创建了两个具有两个单独地址的独立对象。如果没有这些方法,JVM无法知道对象是“相同的”。
请参阅http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()
答案 1 :(得分:1)
考虑如何实施HashMap
。放置时,它首先计算对象hashCode()
以确定放置对象的桶。当它尝试检索对象时,它再次获取其hashCode()
,标识到目标桶,通过存储桶中的链接列表,针对每个对象调用equals()
。如果找到匹配则返回。
换句话说,当您使用HashMap
时,您需要拥有equals()
和hashCode()
的正确匹配实现。
从hashCode()
继承的默认Object
方法无法正确返回相同的hashCode()
,除非对象引用相同。在你的情况下,他们不是。
答案 2 :(得分:0)
多次调用new Cell(0,0)会产生具有不同哈希码的不同对象。您应该为Cell类实现hashCode。
答案 3 :(得分:0)
您可能忘记为hashcode()
实施Cell
函数,这也是在HashMap
中使用用户定义的类所必需的。以下是实现hashcode()
函数的简单且通常准确的方法:
int hashcode(){
return (field1.toString()+field2.toString()+...+fieldN.toString()).hashcode();
}
field1
到fieldN
是您班级中的字段。如果字段是主要字段(即int
),则只需取出toString()
。