为什么 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
的键是有问题的,一般来说,我们应该使用不可变对象作为键。
我创建了一张地图,里面有地图作为测试,外面的地图似乎会忽略其余的地图。我认为它压倒了他们。我还认为这是因为它们都是从 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 mapsm1
andm2
represent the same mappings ifm1.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
实施。
正如已经指出的 Map
作为另一个 Map
的键是有问题的,一般来说,我们应该使用不可变对象作为键。