假设 V 是一个具有名为 K 的单个属性及其 getter 和 setter 的类。
如果我这样做会发生什么:
V v = new V();
v.setK("a");
HashMap<K,V> map = new HashMap<K,V>();
map.put(v.getk(),v);
v.setK("b");
据我所知,这应该会导致某种问题,因为映射键应该是不变的。这里会发生什么?
编辑:考虑键不是一个字符串,而是一个可变对象,如下面的评论中所述。
引用“地图”接口JavaDoc:
如果将可变对象用作映射键,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是映射中的键,则不指定映射的行为。
你根本不应该改变键(以改变它们的“hashCode”/“equals”的方式)。如果你尝试,你肯定会有很长很糟糕的调试。
就像你在图书馆交换书籍一样。索引变得不可靠。您搜索“Bradbury”,但找到“Simak”。
如果您尝试使用v.getk()
它来查找地图,则不会找到条目,因为您已经更改了 v 上的 getter 返回的值。
或者换句话说,地图并没有神奇地与你的 v 对象发生的事情保持同步——它使用(并继续使用)在put()
.
V v = new V();
v.setK("a");
HashMap<K,V> map = new HashMap<K,V>();
map.put(v.getk(),v);
//Nothing will change in the hashmap with this step
v.setK("b");
但问题将出在从地图中获取对象 V 时。如果你调用 map.get(v.getk()),你会得到 null,因为 map 中的值是用对象“a”映射的。但是,由于这个 String "a" 是 inter 你总是可以通过map.get("a");
or从 map 中获取这个对象
V v = new V();
v.setK("a");
map.get(v.getK());
PS:我没有尝试运行这个
通过调用 v.setK(),您不会更改 HashMap 中的键。因此,您的 V 对象中只会有错误的信息。
这个问题的标题具有误导性——您没有更改映射键,就像改变用作映射键的对象一样。当您说 时map.put(x, y)
,您正在创建一个聚合两个独立值的映射条目:一个键和一个值。地图看不到密钥的来源,它只是两个对象。因此,您已经创建了一个映射条目("a", v)
,之后您只是更改了 v 的状态——这不可能影响映射条目的键“a”。另一方面,如果你有一个自己制作的对象 K,比如
public class K {
private String s;
public K(String s) { this.s = s; }
public void setS(String s) { this.s = s; }
public boolean equals(Object o) { return ((K)o).s.equals(this.s); }
public int hashCode() { return s.hashCode(); }
}
现在你做了
final K k = new K("a");
map.put(k, v);
k.setS("b");
map.get(k);
那么您将面临问题 - 您改变了用作映射键的对象。