3

假设 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");

据我所知,这应该会导致某种问题,因为映射键应该是不变的。这里会发生什么?

编辑:考虑键不是一个字符串,而是一个可变对象,如下面的评论中所述。

4

5 回答 5

6

引用“地图”接口JavaDoc:

如果将可变对象用作映射键,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是映射中的键,则不指定映射的行为。

你根本不应该改变键(以改变它们的“hashCode”/“equals”的方式)。如果你尝试,你肯定会有很长很糟糕的调试。

就像你在图书馆交换书籍一样。索引变得不可靠。您搜索“Bradbury”,但找到“Simak”。

于 2012-04-14T12:15:59.313 回答
2

如果您尝试使用v.getk()它来查找地图,则不会找到条目,因为您已经更改了 v 上的 getter 返回的值。

或者换句话说,地图并没有神奇地与你的 v 对象发生的事情保持同步——它使用(并继续使用)在put().

于 2012-04-14T11:01:19.063 回答
2
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:我没有尝试运行这个

于 2012-04-14T11:10:09.800 回答
1

通过调用 v.setK(),您不会更改 HashMap 中的键。因此,您的 V 对象中只会有错误的信息。

于 2012-04-14T11:01:23.367 回答
1

这个问题的标题具有误导性——您没有更改映射键,就像改变用作映射键的对象一样。当您说 时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);

那么您将面临问题 - 您改变了用作映射键的对象

于 2012-04-14T11:05:46.710 回答