Reputation: 19
I'm somewhat of a beginner to java, although I understand the basics. I believed this was the best implementation for my problem, but obviously I may be wrong. This is a mock example I made, and I'm not interested in looking for different implementations. I simply mention I'm not sure if it's the best implementation in the case that it's impossible. Regardless:
Here I have an enum, inside of which I want a map (specifically a LinkedHashMap) as one of the enum object's stored values
enum Recipe {
PANCAKES(true, new LinkedHashMap<>() ),
SANDWICH(true, new LinkedHashMap<>() ),
STEW(false, new LinkedHashMap<>() );
private final boolean tasty;
private final LinkedHashMap<String, String> directions;
// getter for directions
Recipe(boolean tasty, LinkedHashMap<String, String> directions) {
this.tasty = tasty
this.directions = directions;
}
}
(as this would be needed for an enum)
For example, I thought this looked fine
PANCAKES(true, new LinkedHashMap<>(){{
put("Pancake Mix","Pour");
put("Water","Mix with");
put("Pan","Put mixture onto");
}};)
Until I read that this is dangerous and can cause a memory leak. Plus, it isn't the best looking code.
I also found the method:
Map.put(entry(), entry()... entry())
Which can be turned into a LinkedHashMap by passing it through its constructor:
PANCAKES(true, new LinkedHashMap<>(Map.put(entry(), ...)) );
Although I haven't found a way to ensure the insertion order is preserved, since as far as I'm aware Maps don't preserve insertion order.
Of course, there's always the option to store the LinkedHashMaps in a different place outside of the enum and simply put those in manually, but I feel like this would give me a headache managing, as I intend to add to this enum in the future.
Is there any other way to accomplish this?
to clarify, I don't literally need the code to occupy a single line, I just want the LinkedHashMap initialization and population to be written in the same place, rather than storing these things outside of the enum
Upvotes: 1
Views: 301
Reputation: 33004
Without more context, I'd say that Recipe
is kind of a square peg to try to fit into the round hole of enum
. In other words, in the absence of some other requirement or context that suggests an enum is best, I'd probably make it a class and expose public static final
instances that can be used like enum values.
For example:
public class Recipe {
public static final Recipe PANCAKES =
new Recipe(true,
new Step("Pancake Mix","Pour"),
new Step("Water","Mix with"),
new Step("Pan","Put mixture onto")
);
public static final Recipe SANDWHICH =
new Recipe(true
// ...steps...
);
// ...more Recipes ...
@Getter
public static class Step {
private final String target;
private final String action;
private Step(String target, String action ) {
this.target = target;
this.action = action;
}
}
private final boolean tasty;
private final LinkedHashMap<String, Step> directions;
private Recipe(boolean tasty, Step... steps) {
this.tasty = tasty;
this.directions = new LinkedHashMap<>();
for (Step aStep : steps) {
directions.put(aStep.getTarget(), aStep);
}
}
}
You could also do this as anenum
, where the values would be declared like this:
PANCAKES(true,
new Step("Pancake Mix","Pour"),
new Step("Water","Mix with"),
new Step("Pan","Put mixture onto")
),
SANDWHICH(true
// ...steps...
);
but like I said, this feels like a proper class as opposed to an enum.
Upvotes: 2
Reputation: 682
First off, you don't really need to declare the map as a concrete implementation. If you just use Map
then you will have a lot more choices.
enum Recipe {
PANCAKES(true, Map.empty()),
SANDWICH(true, Map.empty()),
STEW(false, Map.empty());
private final boolean tasty;
private final Map<String, String> directions;
// getter for directions
Recipe(boolean tasty, Map<String, String> directions) {
this.tasty = tasty
this.directions = directions;
}
}
Then, assuming you don't have more than 10 directions, you can use this form:
PANCAKES(true, Map.of(
"Pancake Mix","Pour",
"Water","Mix with",
"Pan","Put mixture onto"))
Map.of
creates an immutable map, which is probably what you want for this kind of application, and should not have memory leakage issues.
Upvotes: 0