将地图包含为值;

Rol*_*all 7 java dictionary equals hashcode

直接来自这个 java doc:

这种禁令的一个特例是地图不允许将自己作为关键词包含在内.虽然允许映射将自身包含为值,但建议极其谨慎:equals和hashCode方法不再在这样的映射上很好地定义.

为什么hashcode和equals不再在这样的地图上定义好?

提前致谢.

ssi*_*lar 5

相关部分形成AbstractMap.equals,大多数Map实现都使用它:

            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;
                }
            }
Run Code Online (Sandbox Code Playgroud)

将地图添加为值将导致无限循环.


Nam*_*San 2

Java 文档中该段落的完整引用是:

注意:如果使用可变对象作为映射键,则必须非常小心。如果对象的值以影响等于比较的方式更改,而该对象是映射中的键,则未指定映射的行为。此禁止的一个特殊情况是不允许映射将自身包含为键。虽然允许映射将自身包含为值,但建议格外小心:在此类映射上不再明确定义 equals 和 hashCode 方法。

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

哈希码用于计算存储桶以放置新条目。如果映射本身用作键,那么每次更新/删除/修改新条目时,计算的存储桶都会不同。因此,将来使用映射作为键的查找很可能会失败,因为根据哈希码计算出不同的存储桶。未来的 put 可能无法检测到该键已存在于映射中,然后允许具有相同键的多个条目(但在不同的存储桶中)