Java - Why use EnumMap when enum itself can be used as a map?

2.5k Views Asked by At

I've been reading up Java recently. So I have a enum below that acts as a map with key "JESSIE" and value "My favorite cat".

So why does anyone need to use EnumMap? Thanks

public enum Cat {
    JESSIE("My favorite cat");

    private String description;

    Cat(String description){
        this.description = description;
    }
}
2

There are 2 best solutions below

2
On

The primary reason behind this would be to design the classes in such a way that it holds the attributes that represent its entity and not which it would require a mapping with while querying.

As an example, consider another class Human as follows

@AllArgsConstructor
static class Human {
    String name;
}

Now you could have looked for a Cat to its owner mapping, but how much of a sense would it make to keep the entire Human object referenced for such a mapping? Despite the fact, that you could keep such a reference, what's helpful for the purpose of query ability is to keep such a reference in an additional data structure EnumMap in this case -

EnumMap<Cat, Human> enumMap = new EnumMap<>(Cat.class);
enumMap.put(Cat.JESSIE, new Human("naman"));
enumMap.put(Cat.LUCY, new Human("user"));
1
On

The enum is the key in an EnumMap, and therefore those two things are completely different. You have no way of knowing all the kinds of things you may want to associate with your cats.

The description may be an inherent part of Cat, but you might want to associate cats with their servants, or where they (currently) live or what their preferred meal (currently) is.

EnumMap<Cat, Human> catsServant;
EnumMap<Cat, House> catsHome;
EnumMap<Cat, Meal> catsFood;

Since you don't need to modify Cat to associate it with another object, it makes it a lot easier to use, and your enum would become huge if you filled it with all possible things you might want to associate your cats with.

A second issue is that enums are singletons, which means that if you were to put mutable state (strongly discouraged!) in your Cat by adding a setDescription(String) method, it will change that globally in your program. That may not matter for simple programs or a simple property like description, but it does matter when you have more complex code.

Now a more realistic example. The JDK TimeUnit enum has values such as MINUTE, and the creators couldn't have known of all the possible things that people might want to associate with them. However with an EnumMap I can provide a translation to my native language as follows:

EnumMap<TimeUnit, String> xlate = new EnumMap<>(TimeUnit.class);
xlate.put(TimeUnit.MINUTE, "Minuutti");
xlate.put(TimeUnit.SECOND, "Sekunti");

TimeUnit isn't my class, so I can't edit it to include those translations, and it would be the wrong place anyway.

A related question is why is there a special EnumMap, since you can also use a normal map, such as HashMap<Cat, Human>.