2013-07-05 100 views
7

直接从this Java文档:将containsig本身映射为一个值;

这一禁令的一种特殊情况是,这是不允许的 地图以自身作为一个键。虽然允许将一个包含 的地图作为值包含在内,但建议您格外小心:在这样的地图上,equals和 hashCode方法不再被很好地定义。

为什么哈希码,等于不再得到很好的这样的地图上标示?

在此先感谢。

+2

如果我没记错的话,equals方法会检查映射的内容是平等的。并且这是使用内容的等号方法即地图本身来完成的。我很确定我们最终会出现StackOverflowError –

+0

可能是地图等于函数的样子吗?也许它会导致无限循环?只是一个想法 – Kevin

+0

@MarcoForberg如果我没有记错,最好的做法是检查你正在比较的对象是否真的是你自己,如果是的话,立即返回true。 –

回答

2

从Java文档中的段落的完整报价:

注意:如果使用可变对象作为map的key 很大,一定要小心。如果对象的值以影响等于比较的方式更改,而对象是地图中的关键字,则不会指定地图的行为。这种禁令的一个特例是,不允许地图将自身作为关键字。虽然地图可以包含自身作为值是允许的,但建议您非常小心:equals和hashCode方法在这样的地图上不再被很好地定义。

AbstractMap.hashCode()方法使用映射中键值对的哈希码来计算哈希码。因此,每次修改地图时,从该方法生成的哈希码都会更改。

散列码用于计算存储桶以放置新条目。如果地图本身被用作关键字,则每次更新/删除/修改新条目时,计算出的存储桶都会有所不同。因此,将地图作为关键字的未来查找很可能会失败,因为根据哈希代码计算不同的存储桶。未来的投入可能无法检测到密钥已经存在于地图中,然后允许具有相同密钥(但在不同桶中)的多个条目

1

如果相同的键映射相同的值,则两个映射相等。 (在一些实现中。)因此为了检查平等,应该检查每个成员的平等。

因此,如果地图包含自身,则会得到无限次的等式检查递归。

散列函数也是如此,因为这些散列函数可以根据地图中元素的散列值进行计算。

实施例:

Map<Int, Object> ma; 
Map<Int, Object> mb; 
Map<Int, Object> mc; 

ma.put(1, ma); 
ma.put(2, mb); 
mc.put(1, ma); 
mc.put(2, mb); 

作为人,我们可以看到mamc是自定义相等。计算机会在两张地图上看到两张地图(空白地图),这很好。它会在mc和ma的另一张地图上看到1张地图。它会检查这些地图是否相同。为了确定这一点,它再次检查1的两个值是否相等。然后再次。

请注意,这不是所有实现的情况。有些实现可能会检查内存中对象被保存的位置是否相等,但是每个递归检查都会无限循环。

5

其用于通过最Map实现有关部分形式AbstractMap.equals:

  Iterator<Entry<K,V>> i = entrySet().iterator(); 
      while (i.hasNext()) { 
       Entry<K,V> e = i.next(); 
       K key = e.getKey(); 
       V value = e.getValue(); 
       if (value == null) { 
        if (!(m.get(key)==null && m.containsKey(key))) 
         return false; 
       } else { 
        if (!value.equals(m.get(key))) // would call equals on itself. 
         return false; 
       } 
      } 

添加在地图上以值将导致无限循环。

+1

equals()方法的第一条语句是** if(o == this)return true; **我认为这会阻止无限循环,因为它会立即返回并永远不会执行您突出显示的代码。 –

+0

该死的你是对的。答案需要不加标记。也许这是因为它是如此实现依赖,他们没有定义它不推荐它。 – ssindelar

+0

好吧,您可以通过创建两个地图来创建问题,将一个地图放入另一个地图,然后在另一个地图上用另一个地图作为参数调用equals。或者您只需将一张地图放入自身并调用hashcode() –

0

试图解释它:

equals方法将遍历两个地图和调用地图的每个键和值的equals方法。所以,如果一个地图包含它自己,你会一直不停地调用equals方法。

散列码发生同样的事情。

来源:类的源代码AbstractMap