我只是想知道,如果HashMap的关键字是可变的,那么会发生什么,下面的测试程序会演示,当我们都等于和hashCode方法返回时,我无法理解
true和相同的值,为什么hashmap.containsKey返回false.
true和相同的值,为什么hashmap.containsKey返回false.
public class MutableKeyHashMap { public static void main(String []a){ HashMap<Mutable,String> map = new HashMap<Mutable,String>(); Mutable m1 = new Mutable(5); map.put(m1,"m1"); Mutable m2 = new Mutable(5); System.out.println(map.containsKey(m2)); m2.setA(6); m1.setA(6); Mutable m3 = map.keySet().iterator().next(); System.out.println(map.containsKey(m2)+" "+m3.hashCode()+" "+m2.hashCode()+" "+m3.equals(m2)); } } class Mutable { int a; public Mutable(int a) { this.a = a; } @Override public boolean equals(Object obj) { Mutable m = (Mutable) obj; return m.a == this.a ? true : false; } @Override public int hashCode(){ return a; } public void setA(int a) { this.a = a; } public int getA() { return a; } }
这个输出:
true
false 6 6 true
解决方法
javadoc解释了
Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.
基本上,不要在地图中使用可变对象作为键,你将被烧毁
要推断,因为文档可能不清楚,我相信这里的相关点是以影响equals的方式进行更改,而且您似乎假设每次调用包含的equals(Object)时都会调用该对象.文档没有说,这个措辞意味着它们可能被允许缓存计算.
看看source,似乎是因为你的hashCode返回一个不同的值(现在是5,现在是6),它可能是根据实现细节在不同的桶中查找的.