带枚举键的不可变地图的Map.of vs EnumMap

时间:2018-09-11 17:35:59

标签: java performance dictionary enums time-complexity

EnumMap使用限制,即映射的所有键都来自同一enum,以获取性能优势:

  

枚举映射在内部表示为数组。这种表示非常紧凑且高效。

在这种情况下,键和值存储在单独的数组中,并且值按序排列。迭代是通过内部EnumMapIterator类完成的。

由各种Map.of方法创建的不可变映射使用限制,即映射不会在结构上进行更改以获取性能优势。如果映射的大小不是0或1,它将使用MapN内部类,该内部类还将其条目存储在数组中。在这种情况下,该值在其键之后的1个索引中存储。迭代是通过内部MapNIterator完成的。

对于大小为2或更大的enum键的不变映射,可以同时满足上述两个要求,哪种映射的性能更好? (条件可以是空间效率,containsKeycontainsValueget的时间效率以及entrySetkeySetvalues的迭代效率。 )

1 个答案:

答案 0 :(得分:1)

  

该图可提供更好的空间效率,并为其操作和迭代提供时间效率:containsKeycontainsValuegetentrySetkeySet和{ {1}}?

您要提出1 + 6(或2 * 6,具体取决于理解方式)的问题,这有点太多了。如果您想确定的答案,则必须专注于一件事并对其进行概要分析(除非您发现一个非常有趣的问题,否则没人愿意为您做这件事)。


values的空间效率必须更好。无需存储密钥,因为可以使用共享的枚举数组。不需要a holes-containing hash lookup array

可能会有例外,例如基于巨大枚举的小地图。


最重要的操作是EnumMap。使用getit involves no lookup,仅trivial class comparison和数组访问权限。对于EnumMap,有一个loop,对于枚举,通常在第一次迭代后终止,因为Map.of(...)IMHO stupid,但通常分布良好。

很明显Enum.hashCode基于相同的查找。

我怀疑,我曾经使用过containsKey,但是它没有比线性搜索更聪明的了。由于漏洞,我期望containsValue会获得小小的胜利(需要琐碎的null测试,但会导致分支预测错误)。

其余三个操作不值得查询,因为它们返回的集合中不包含任何数据,仅指向地图,即恒定时间操作。例如,EnumMap只是委托给map.keySet().contains(x)

迭代的效率将是一个更有趣的问题,但您没有提出疑问。