51

Is it possible in Java to make a Dictionary with the items already declared inside it? Just like the below C# code:

   Dictionary<string, int> d = new Dictionary<string, int>()
    {
        {"cat", 2},
        {"dog", 1},
        {"llama", 0},
        {"iguana", -1}
    };

How do I do this and what type do I use? I've read that Dictionary is obsolete.

WildBamaBoy
  • 2,663
  • 6
  • 25
  • 23

5 Answers5

75

This will do what you want:

Map<String,Integer> map = new HashMap<String, Integer>(){{
    put("cat", 2);
    put("dog", 1);
    put("llama", 0);
    put("iguana", -1);
}};

This statement creates an anonymous subclass of HashMap, where the only difference from the parent class is that the 4 entries are added during instance creation. It's a fairly common idiom in the Java world (although some find it controversial because it creates a new class definition).

Because of this controversy, as of Java 9 there is a new idiom for conveniently constructing maps: the family of static Map.of methods.

With Java 9 or higher you can create the map you need as follows:

Map<String, Integer> map = Map.of(
    "cat", 2,
    "dog", 1,
    "llama", 0,
    "iguana", -1
);

With larger maps, this alternative syntax may be less error-prone:

Map<String, Integer> map = Map.ofEntries(
    Map.entry("cat", 2),
    Map.entry("dog", 1),
    Map.entry("llama", 0),
    Map.entry("iguana", -1)
);

(This is especially nice if Map.entry is statically imported instead of being referenced explicitly).

Besides only working with Java 9+, these new approaches are not quite equivalent to the previous one:

  • They don't allow you to specify what Map implementation is used
  • They only create immutable maps
  • They don't create an anonymous subclass of Map

However, these differences shouldn't matter for many use cases, making this a good default approach for newer versions of Java.

Sean Reilly
  • 21,526
  • 4
  • 48
  • 62
  • 2
    And here is an explanation on what this is doing. http://techpolesen.blogspot.com/2007/08/java-initializers-add-elements-to.html – Josh Smeaton Jul 31 '11 at 00:18
  • Hmmm... double braces syntax is not generally considered good style – Luigi Plinge Jul 31 '11 at 00:21
  • @Luigi You're right, I'll change my answer (won't do anything though :P) – fireshadow52 Jul 31 '11 at 00:22
  • 3
    The extra braces are not a style-thing. They are both functional and necessary to denote the code as an initializer block. – Affe Jul 31 '11 at 00:42
  • @Affe - you are aware we are creating a new anonymous class for each such initialization? And what will happen if you try to serialize anything in the map? And the performance impact? (http://stackoverflow.com/questions/924285/efficiency-of-java-double-brace-initialization) Even the writer of the article linked to above says he wouldn't use it in production code. – Luigi Plinge Jul 31 '11 at 00:53
  • 1
    I was talking to fireshadow, who thought you meant "use one brace, not two" not "don't anonymously subclass JavaSE library classes just to save yourself a bit of typing." – Affe Jul 31 '11 at 01:07
  • 1
    @Josh Smeaton: Nice article, although there is a tiny mistake in it: the inner braces are an instance initializer, not a static initializer. – Sean Reilly Jul 31 '11 at 08:11
12
Map<String,Integer> map = new HashMap<String, Integer>(){{
put("cat", 2);
put("dog", 1);
put("llama", 0);
put("iguana", -1);
}};
fireshadow52
  • 6,298
  • 2
  • 30
  • 46
5

Bite the bullet and type out the map name!

    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("cat", 2);
    map.put("dog", 1);
    map.put("llama", 0);
    map.put("iguana", -1);

You could also do something like this, which might save some typing with a long list:

    Object[][] values = {
        {"cat", 2},
        {"dog", 1},
        {"llama", 0},
        {"iguana", -1}
    };

    for (Object[] o : values) {
        map.put((String) o[0], (Integer) o[1]);
    }
Luigi Plinge
  • 50,650
  • 20
  • 113
  • 180
3

If you use the Guava library, you can use its ImmutableMap class, either by itself (examples 1 and 2), or as an initializer for a HashMap (examples 3 and 4):

Map<String, Integer> map1 = ImmutableMap.<String, Integer> builder()
    .put("cat", 2)
    .put("dog", 1)
    .put("llama", 0)
    .put("iguana", -1)
    .build();
Map<String, Integer> map2 = ImmutableMap.of(
    "cat", 2,
    "dog", 1,
    "llama", 0,
    "iguana", -1
);
Map<String, Integer> map3 = Maps.newHashMap(
    ImmutableMap.<String, Integer> builder()
    .put("cat", 2)
    .put("dog", 1)
    .put("llama", 0)
    .put("iguana", -1)
    .build()
);
Map<String, Integer> map4 = Maps.newHashMap( ImmutableMap.of(
    "cat", 2,
    "dog", 1,
    "llama", 0,
    "iguana", -1)
);
Sean Reilly
  • 21,526
  • 4
  • 48
  • 62
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
0

Java7 almost introduced "collection literals" that would allow syntax like that. They'll probably try to shove it in Java8. I have no idea what is wrong with these people.

This can be easily achieved by some kind of wrapper API

Map<String,Integer> map = Maps.<String,Integer>empty()
    .put("cat", 2).put("dog",1)....; 

Not too bad. I would prefer something like

map("cat", "dog", ... )
.to(  1,     2,   ... );

This kind of thing must have been implemented by various people, unfortunately the standard API doesn't inculde such things.

irreputable
  • 44,725
  • 9
  • 65
  • 93