Issue
Is it possible to declare and initialize a Hashtable
or Map
, so we don't have to declare and initialize on two different steps?
// declare first
Hashtable<String, Integer> numbers = new Hashtable<String, Integer>(3);
// then initialize
numbers.put("one", 1);
numbers.put("two", 2);
numbers.put("three", 3);
In ruby and javascript, for example, there are literals to define those:
numbers = {
one: 1,
two: 2,
three: 3,
}
Solution
For Java 9 and beyond, you can make use of Map#of
, as well as Map#ofEntries
with Map#entry
:
Map<String, String> example = Map.ofEntries(
Map.entry("1", "one"),
Map.entry("2", "two"),
Map.entry("3", "three"),
//...
);
For shorter literals (10 or less entries), you can use Map#of
directly (albeit with a slightly confusing syntax of Key1, Value1, Key2, Value2, ...
):
Map<String, String> example = Map.of("1", "one", "2", "two");
Prior to Java 9, this would typically only be needed for initializing constant Map
objects, for which a static
initializer block is also useful:
private static final Map<String, String> MY_CONSTANT;
static {
Map<String, String> setup = new HashMap<>();
setup.put("1", "one");
setup.put("2", "two");
setup.put("3", "three");
MY_CONSTANT = Collections.unmodifiableMap(setup);
}
This will allow you to create a constant Map
while allowing you to modify the map before it is set.
As pointed out by @Pshemo, there are numerous reasons to avoid double-brace initialization, however the notable exception to the "rule" is typically in constants much like the above example (as numerous anonymous classes would not be made). However, it is still possible to work around the need for double-brace initialization even this case, so it is overall best to avoid if possible. The only case I can think of this not being possible is within the context of a constant within an enum
class, where the double-brace init may truly be the only true way to make this work.
Answered By - Rogue
Answer Checked By - Marilyn (JavaFixing Volunteer)