简体   繁体   English

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

[英]Map.of vs EnumMap for immutable map with enum keys

An EnumMap uses the restriction that all keys of a map will be from the same enum to gain performance benefits: EnumMap使用限制,即映射的所有键都将来自同一enum以获取性能优势:

Enum maps are represented internally as arrays. 枚举映射在内部表示为数组。 This representation is extremely compact and efficient. 这种表示非常紧凑和高效。

In this case, the keys and values are stored in separate arrays and the values are ordinal-ordered. 在这种情况下,键和值存储在单独的数组中,并且值按序排列。 Iteration is done with the internal EnumMapIterator class. 迭代是通过内部EnumMapIterator类完成的。

An immutable map created by the various Map.of methods use the restriction that the map will not change structurally to gain performance benefits. 由各种Map.of方法创建的不可变映射使用限制,即该映射将不会在结构上进行更改以获取性能优势。 If the map is not of size 0 or 1, it uses the MapN internal class that also stores its entries in an array. 如果地图的大小不为0或1,它将使用MapN内部类,该类还将其条目存储在数组中。 In this case, the value is stored 1 index after its key. 在这种情况下,该值在其键之后的1个索引中存储。 Iteration is done with the internal MapNIterator . 迭代是通过内部MapNIterator完成的。

For an immutable map of enum keys of size 2 or more, which answers both of the above's requirements, which map performs better? 对于大小为2或更大的不可变enum键的映射,哪个可以满足上述两个要求,哪个映射的性能更好? (Criteria could be space efficiency, time efficiency for containsKey , containsValue , get , and iteration efficiency of entrySet , keySet and values .) (条件可能是空间效率, containsKeycontainsValueget时间效率,以及entrySetkeySetvalues迭代效率。)

which map gives better space efficiency, and time efficiency for its operations and iteration: containsKey , containsValue , get , entrySet , keySet and values ? 哪个地图可提供更好的空间效率以及操作和迭代的时间效率: containsKeycontainsValuegetentrySetkeySetvalues

You're raising 1 + 6 (or 2 * 6, depending on how it's understood) questions, that's a bit too much. 您提出1 + 6(或2 * 6,具体取决于理解方式)的问题,这有点太多了。 If you want a definite answer, you have to concentrate on a single thing and profile it (nobody's gonna do it for you unless you find a very interesting problem). 如果您想确定的答案,则必须专注于一件事并对其进行概要分析(除非您发现一个非常有趣的问题,否则没人愿意为您做这件事)。


The space efficiency for an EnumMap simply must be better. EnumMap的空间效率必须更好。 There's no need to store the keys as a shared enum array can be used. 无需存储密钥,因为可以使用共享的枚举数组。 There's no need for a holes-containing hash lookup array . 不需要包含空洞的哈希查找数组

There may be exceptions like a small map based on a huge enum. 可能会有例外,例如基于巨大枚举的小地图。


The most important operation is get . 最重要的操作是get With an EnumMap , it involves no lookup , just a trivial class comparison and an array access. 使用EnumMap它不涉及查找 ,仅涉及琐碎的类比较和数组访问。 With Map.of(...) , there's a loop , which for enums, usually terminates after the first iteration as Enum.hashCode is IMHO stupid , but usually well distributed. 使用Map.of(...) ,有一个循环 ,对于枚举,通常在第一次迭代后终止,因为Enum.hashCodeIMHO愚蠢的 ,但通常分布良好。

As containsKey is based on the same lookup, it's clear. 很清楚,因为containsKey基于相同的查找。

I doubt, I've ever used containsValue , but it doesn't do anything smarter than linear search. 我怀疑,我曾经使用过containsValue ,但是它没有比线性搜索更聪明的了。 I'd expect a tiny win for EnumMap because of the holes (needing trivial null test, but causing branch mispredictions). 由于漏洞,我期望EnumMap会取得小小的胜利(需要琐碎的null测试,但会导致分支预测错误)。

The remaining three operations are not worth looking up as they return a collection containing no data and simply pointing to the map, ie, a constant time operation. 其余三个操作不值得查询,因为它们返回的集合中不包含任何数据,仅指向地图,即恒定时间操作。 For example, map.keySet().contains(x) simply delegates to map.containsKey() . 例如, map.keySet().contains(x)仅委托给map.containsKey()

The efficiency of the iteration would be a more interesting question, but you didn't ask it. 迭代的效率将是一个更有趣的问题,但您没有提出这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM