为什么 HashMap 会忽略具有来自同一超类的键的条目?

Why will HashMap ignore entries with keys from the same Superclass?

我创建了一张地图,里面有地图作为测试,外面的地图似乎会忽略其余的地图。我认为它压倒了他们。我还认为这是因为它们都是从 Map 扩展而来的,所以当它们不是时,它将它们视为同一个实例。

Map<Map<Integer, String>,String> maps=new HashMap<>();
maps.put(new HashMap<Integer, String>(),"HashMap");
maps.put(new TreeMap<Integer, String>(),"TreeMap");
maps.put(new LinkedHashMap<Integer, String>(),"LinkedHashMap");
maps.put(new Hashtable<Integer, String>(),"Hashtable");

将地图打印到日志中将仅显示最后添加的地图:

maps: {{}=Hashtable}

我尝试了其他 Map 实现,除了 TreeMap 之外,所有实现都具有相同的行为,由于 HashMap 没有实现 Comparable.

,它将抛出异常

这是预期的行为吗?为什么 HashMap 会这样?

当我们查看 documentation of Map::equals 时,我们看到此方法

Returns true if the given object is also a map and the two maps represent the same mappings. More formally, two maps m1 and m2 represent the same mappings if m1.entrySet().equals(m2.entrySet()).

由于contract between Object::equals and Object::hashCode, this means that those maps will also have the same hash code. This, in return, means that they are, for Map::put,无法区分。因此,示例程序中的每个 put(...) 都会覆盖之前的 put,从而导致最终地图大小为 1,只有 entrySet() 中的 HashTable

所以是的,这是预期的行为。它不仅适用于 HashMap,而且适用于所有 Map 实施。

正如已经指出的 by Pshemo,使用 Map 作为另一个 Map 的键是有问题的,一般来说,我们应该使用不可变对象作为键。