javadictionaryinitialization

Can I declare and initialize a map in java with a literal?


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