我遇到了有关 HashMap
的问题。经过一番调试没有结果后,我编写了一小段代码来测试HashMap
。但结果却更加令人困惑!
public static void main(String[] args) {
Point a = new Point(0, 0); // java.awt.Point
Map<Point, Integer> map = new HashMap<Point, Integer>();
map.put(a, 0);
System.out.println(map.containsKey(new Point(0, 0))); // true
a.x = 1;
System.out.println(map.containsKey(new Point(0, 0))); // false
System.out.println(map.containsKey(new Point(1, 0))); // false
System.out.println(map.containsKey(a)); // false
}
我期望第二个或第三个输出能给我一个真实的结果,而第四个输出肯定是真实的。但事实似乎并不认同。
关于我改变 key 的意图,我使用 map 来保存一些小怪。生物具有 Point 字段,并且 map 的键使用相同的引用。然后我也许可以通过它的协调来寻找生物并且也可以轻松地改变协调。
最佳答案
您可以在 source code 中查找。并理解它,尽管并不像我想象的那么容易。
问题是,当您更改 x
的值时,哈希树中的对象似乎位于错误的位置,我将对此进行说明。
您将 key 放入一棵树中,如下所示:
.../-- Point(0,0)
root
---\.. nothing
如果将 Point(1,0) 放入其中,它将如下所示:
.../.. nothing
root
...\.. Point(1,0)
因此,当您更改 key 时,树看起来像这样:
.../.. Point(1,0)
root
...\.. nothing
现在您寻找Point(1,0)
,并且 map 遍历了该键应属于的较低分支,但什么也没有。当您查找 Point(0,0)
时,它会遍历存在错误键的上分支。
因此,永远不要更改对象 .hashCode()
中的值,这一点很重要。相反,使用该对象的新实例进行替换或使用该对象的克隆来放置在 HashMap
中。
或者,如果您想更改键,您可以将其从 map 中删除,更改它然后将其放回原处。如下所示:
public static void main(String[] args) {
Point a = new Point(0, 0); // java.awt.Point
Map<Point, Integer> map = new HashMap<Point, Integer>();
map.put(a, 0);
System.out.println(map.containsKey(new Point(0, 0))); // true
Integer value = map.remove(a);
a.x = 1;
map.put(a,value);
System.out.println(map.containsKey(new Point(0, 0))); // false
System.out.println(map.containsKey(new Point(1, 0))); // true
System.out.println(map.containsKey(a)); // true
}
您可能希望将remove、alter 和put 方法转移到对象内自己的方法以使其可用。您可以调用它 setAndRelocate(int newX, int newY, Map container)
并将其放回到常规代码中的一行。
关于java - HashMap 如何保存和查找键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23075576/