1

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

user1803551
  • 12,965
  • 5
  • 47
  • 74
  • @DominikSandjaja Same thing they did [here](https://stackoverflow.com/questions/322715/when-to-use-linkedlist-over-arraylist-in-java), [here](https://stackoverflow.com/a/17708526/1803551), [here](https://stackoverflow.com/questions/20116660/hashset-vs-treeset-vs-linkedhashset-on-basis-of-adding-duplicate-value) etc. – user1803551 Sep 11 '18 at 17:49
  • `Map.of` doesn't make any guarantee about the implementation attributes you've referred to (`MapN` is even package-private). For this reason alone, I'd almost always use `EnumMap` in this case. The rest can only be settled by testing/benchmarking. – ernest_k Sep 11 '18 at 17:51
  • 1
    Interesting question. @DominikSandjaja that doesn't look like a valid response. not everyone can JMH and read bytecode. this site answers questions much much simpler beginner questions and you don't tell them what do you want the community to do, go read a book, or go do a degree in CS, or take private lessons. This is what this site is for and this question is far from trivial – Mark Sep 11 '18 at 17:59

1 Answers1

2

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, i.e., 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.

maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • Well, it's actually 1 question of how the 2 compare, just like the linked questions in the comments. I agree it wasn't clear, but I asked about the iteration: "time efficiency for its operations and iteration". I rephrased the question to reflect that if you'd like to answer it. – user1803551 Sep 15 '18 at 14:29
  • @user1803551 Well, Id' always prefer the `EnumMap`, unless the `enum` is really much bigger than the number of elements. You may need the immutability (but then consider using Guava). – maaartinus Sep 17 '18 at 02:40