【问题标题】:java.util.Map.put(key, value) - what if value equals existing value?java.util.Map.put(key, value) - 如果值等于现有值怎么办?
【发布时间】:2012-09-25 17:47:52
【问题描述】:

来自规范:“如果映射先前包含键的映射,则旧值将替换为指定值。”我想知道 value.equals(the old value) 但 value != old value 的情况。我对规范的解读是,旧值仍必须被替换。对吗?

【问题讨论】:

  • 它将替换,这样您就可以“清除” System.properties() 值;)
  • javadoc 是明确的:新值替换旧值,无论它们是否相等或相同。
  • @assylias 谢谢,“明确”是一个很好的表达方式,现在我看到该语言不允许进行相等检查。新值替换旧值句点。
  • 如果它们是相等的,那么这甚至不重要——它们是可以互换的。

标签: java collections map


【解决方案1】:

如果新键与现有键匹配,则无论其值如何,映射的值都将被替换,例如即使oldValue.equals(newValue)true

我认为我们不需要查看源代码或依赖测试代码:这在 Map.put 的文档中是明确的,我们在其中找到:

如果映射先前包含键的映射,则旧值将替换为指定值。 (当且仅当 m.containsKey(k) 将返回 true 时,映射 m 才被称为包含键 k 的映射。)

【讨论】:

  • 这不是问题。问题是:当键已经存在时,值会发生什么?这是替换的。即使值相等?
  • 像@assylias 一样,您指出了我推理中的缺陷。语言没有解释的余地​​。而且您没有使用 HashMap,这对我很重要,因为这不是 Python 或 PHP,其中允许参考实现作为规范的替代品。但是,为了捍卫确实使用 HashMap 的答案,这是一个接口,而不是实现细节,如果 Map 实现在这一点上模棱两可,那就太疯狂了。
【解决方案2】:

不检查值相等,仅检查键相等。如果您指定的键与映射中已经存在的键匹配,则该对象将被其相等替换。

如果之前已将某个值与键关联,则该值将由put 方法返回。这是来自HashMap<K,V>的sn-p:

for (Entry<K,V> e = table[i]; e != null; e = e.next) {
    Object k;
    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
        V oldValue = e.value;
        e.value = value;
        e.recordAccess(this);
        return oldValue;
    }
}

【讨论】:

    【解决方案3】:

    是的,没错。一个简单的测试会告诉你:

    Integer a = new Integer(1);
    Integer b = new Integer(1);
    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("key", a);
    map.put("key", b);
    System.out.println("Value is b : " + (map.get("key") == b));
    

    【讨论】:

    • 没有。该文档清楚地说:“将指定的值与此映射中的指定键相关联”。如果在某些情况下该值实际上与键无关,文档会说明这一点。
    【解决方案4】:

    是的,您的理解是正确的,如果map 中存在一个的相等值,它将被替换为新值。

    【讨论】:

      【解决方案5】:

      我相信你是对的。您可以使用如下代码进行检查:

      Map<String, String> strsMap = new HashMap<String, String>();
      String myString1 = new String("mystring");
      String myString2 = new String("mystring");
      strsMap.put("str", myString1);
      System.out.println(myString1 == strsMap.put("str", myString2));
      System.out.println(myString2 == strsMap.get("str");
      

      【讨论】:

      • 那么Map 的其他实现呢?举例证明不是证明。
      • 文档明确指出这是预期的行为,如果该键存在值,它将被替换并返回旧值。但为了完整起见,上面的代码为HashMapHashtableTreeMapWeakHashMap 打印相同的内容,它们是直接的实现。其他实现(参见top of the docs)扩展了这些实现之一或使用组合/委托。 EnumMapIdentityHashMap 也有这种行为。我会说它非常具体。
      • @SteveKuo 来自文档:“如果映射先前包含键的映射,则旧值将替换为指定值。”并且:“返回:key 关联的先前值,如果没有 key 的映射,则返回 null。”不这样做是违反接口契约的,因此您可以在所有地图实现中预期这种行为。
      • 是的,我知道文档是怎么说的,但您的回答只不过是测试单个实现。
      猜你喜欢
      • 1970-01-01
      • 2019-10-16
      • 2011-05-30
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 2018-03-04
      • 2020-10-14
      • 2021-11-05
      相关资源
      最近更新 更多