EnumMap
使用限制,即映射的所有键都来自同一enum
,以获取性能优势:
枚举映射在内部表示为数组。这种表示非常紧凑且高效。
在这种情况下,键和值存储在单独的数组中,并且值按序排列。迭代是通过内部EnumMapIterator
类完成的。
由各种Map.of
方法创建的不可变映射使用限制,即映射不会在结构上进行更改以获取性能优势。如果映射的大小不是0或1,它将使用MapN
内部类,该内部类还将其条目存储在数组中。在这种情况下,该值在其键之后的1个索引中存储。迭代是通过内部MapNIterator
完成的。
对于大小为2或更大的enum
键的不变映射,可以同时满足上述两个要求,哪种映射的性能更好? (条件可以是空间效率,containsKey
,containsValue
,get
的时间效率以及entrySet
,keySet
和values
的迭代效率。 )
答案 0 :(得分:1)
该图可提供更好的空间效率,并为其操作和迭代提供时间效率:
containsKey
,containsValue
,get
,entrySet
,keySet
和{ {1}}?
您要提出1 + 6(或2 * 6,具体取决于理解方式)的问题,这有点太多了。如果您想确定的答案,则必须专注于一件事并对其进行概要分析(除非您发现一个非常有趣的问题,否则没人愿意为您做这件事)。
values
的空间效率必须更好。无需存储密钥,因为可以使用共享的枚举数组。不需要a holes-containing hash lookup array。
可能会有例外,例如基于巨大枚举的小地图。
最重要的操作是EnumMap
。使用get
,it involves no lookup,仅trivial class comparison和数组访问权限。对于EnumMap
,有一个loop,对于枚举,通常在第一次迭代后终止,因为Map.of(...)
为IMHO stupid,但通常分布良好。
很明显Enum.hashCode
基于相同的查找。
我怀疑,我曾经使用过containsKey
,但是它没有比线性搜索更聪明的了。由于漏洞,我期望containsValue
会获得小小的胜利(需要琐碎的null测试,但会导致分支预测错误)。
其余三个操作不值得查询,因为它们返回的集合中不包含任何数据,仅指向地图,即恒定时间操作。例如,EnumMap
只是委托给map.keySet().contains(x)
。
迭代的效率将是一个更有趣的问题,但您没有提出疑问。