3

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;
    }
}
user2606235
  • 71
  • 1
  • 4

2 Answers2

5

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

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • The related question section is not much in the interest/scope of this question and is answered pretty clearly in the [other Q&A](https://stackoverflow.com/questions/53406636/why-use-enummap-instead-of-hashmap). – Naman Mar 28 '20 at 18:27
3

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"));
Naman
  • 27,789
  • 26
  • 218
  • 353
  • thanks for your answer and explanation, just curious - are there differences between my design below vs. using a enummap which you just mentioned? do they both do the same thing? thanks again ``` public enum Cat { JESSIE(new Human("naman")); private Human human; Cat(Human human){ this.human = human; } } ``` – user2606235 Mar 29 '20 at 11:53
  • 1
    @user2606235 The main difference is the extensibility and the threshold that your solution would reach. For example, how many such mapping `Human`s can you keep in the `enum`, they could all have different roles? – Naman Mar 29 '20 at 13:22