我有大量使用自定义密钥和比较器的地图。我注意到当我像下面这样使用代码创建地图时,
var map = TreeMap<>( someCustomComparator );
接着,我使用以下代码创建一个不可变的(小而快速的)副本:
map = Map.copyOf( map );
然后,map.get(similarObject)
就无法检索到someObject
,即使在使用比较器someCustomComparator
比较下,someObject
和similarObject
相等(“具有相同的等价类”)。
通过对API进行调试,我发现Map.copyOf
返回一个使用Object::equals
来比较键的映射实现,即它没有使用用于构造原始映射的比较器(在我的示例中,这将是someCustomComparator
)。显然,当someObject
和similarObject
不是同一个对象但在someCustomComparator
下具有相同的等价类而Object::equals
没有被覆盖时,这将产生奇怪的结果。
map.get( similarObject ) ==> someObject
在执行map = Map.copyOf(map)
指令之前,以及
map.get( similarObject ) ==> null
map = Map.copyOf( map )
指令执行后,这种行为是否可以预期我必须接受或者应该报告Java缺陷?
(请注意,some/similarObject
的类也实现了comparable
,但这也被Map.copyOf
实现所忽略。)
(我认为这种行为在所有的集合copyOf实现中都是普遍存在的。)
new TreeMap<K, V>(SortedMap<K, ? extends V> oldMap);
是更加安全的(类型和排序)! - xerx593java.util.Map
没有“顺序”..它只有键和值...如果需要顺序,您需要一个(更具体的)java.util.SortedMap
..至少。 - xerx593