简体   繁体   中英

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:

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.

An immutable map created by the various Map.of methods use the restriction that the map will not change structurally to gain performance benefits. If the map is not of size 0 or 1, it uses the MapN internal class that also stores its entries in an array. In this case, the value is stored 1 index after its key. Iteration is done with the internal 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? (Criteria could be space efficiency, time efficiency for containsKey , containsValue , get , and iteration efficiency of entrySet , keySet and values .)

which map gives better space efficiency, and time efficiency for its operations and iteration: containsKey , containsValue , get , entrySet , keySet and values ?

You're raising 1 + 6 (or 2 * 6, depending on how it's understood) questions, that's a bit too much. 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. 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 . With an EnumMap , it involves no lookup , just a trivial class comparison and an array access. 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.

As containsKey is based on the same lookup, it's clear.

I doubt, I've ever used containsValue , but it doesn't do anything smarter than linear search. I'd expect a tiny win for EnumMap because of the holes (needing trivial null test, but causing branch mispredictions).

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() .

The efficiency of the iteration would be a more interesting question, but you didn't ask it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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