How to directly initialize a HashMap (in a literal way)?
All Versions
In case you happen to need just a single entry: There is Collections.singletonMap("key", "value")
.
For Java Version 9 or higher:
Yes, this is possible now. In Java 9 a couple of factory methods have been added that simplify the creation of maps :
// this works for up to 10 elements:
Map<String, String> test1 = Map.of(
"a", "b",
"c", "d"
);
// this works for any number of elements:
import static java.util.Map.entry;
Map<String, String> test2 = Map.ofEntries(
entry("a", "b"),
entry("c", "d")
);
In the example above both test
and test2
will be the same, just with different ways of expressing the Map. The Map.of
method is defined for up to ten elements in the map, while the Map.ofEntries
method will have no such limit.
Note that in this case the resulting map will be an immutable map. If you want the map to be mutable, you could copy it again, e.g. using mutableMap = new HashMap<>(Map.of("a", "b"));
(See also JEP 269 and the Javadoc)
For up to Java Version 8:
No, you will have to add all the elements manually. You can use an initializer in an anonymous subclass to make the syntax a little bit shorter:
Map<String, String> myMap = new HashMap<String, String>() {{
put("a", "b");
put("c", "d");
}};
However, the anonymous subclass might introduce unwanted behavior in some cases. This includes for example:
- It generates an additional class which increases memory consumption, disk space consumption and startup-time
- In case of a non-static method: It holds a reference to the object the creating method was called upon. That means the object of the outer class cannot be garbage collected while the created map object is still referenced, thus blocking additional memory
Using a function for initialization will also enable you to generate a map in an initializer, but avoids nasty side-effects:
Map<String, String> myMap = createMap();
private static Map<String, String> createMap() {
Map<String,String> myMap = new HashMap<String,String>();
myMap.put("a", "b");
myMap.put("c", "d");
return myMap;
}
There is no direct way to do this - As of 2021, Java has no Map literals (yet - I think they were proposed for Java 8, but didn't make it).
Some people like this:
Map<String,String> test = new HashMap<String, String>(){{
put("test","test"); put("test","test");}};
This creates an anonymous subclass of HashMap, whose instance initializer puts these values. (By the way, a map can't contain twice the same value, your second put will overwrite the first one. I'll use different values for the next examples.)
The normal way would be this (for a local variable):
Map<String,String> test = new HashMap<String, String>();
test.put("test","test");
test.put("test1","test2");
If your test
map is an instance variable, put the initialization in a constructor or instance initializer:
Map<String,String> test = new HashMap<String, String>();
{
test.put("test","test");
test.put("test1","test2");
}
If your test
map is a class variable, put the initialization in a static initializer:
static Map<String,String> test = new HashMap<String, String>();
static {
test.put("test","test");
test.put("test1","test2");
}
If you want your map to never change, you should after the initialization wrap your map by Collections.unmodifiableMap(...)
. You can do this in a static initializer too:
static Map<String,String> test;
{
Map<String,String> temp = new HashMap<String, String>();
temp.put("test","test");
temp.put("test1","test2");
test = Collections.unmodifiableMap(temp);
}
(I'm not sure if you can now make test
final ... try it out and report here.)
Since Java 9, you also have the Map.of(...) and Map.ofEntries() syntax, as explained in the answer from yankee.
This is one way.
Map<String, String> h = new HashMap<String, String>() {{
put("a","b");
}};
However, you should be careful and make sure that you understand the above code (it creates a new class that inherits from HashMap). Therefore, you should read more here: http://www.c2.com/cgi/wiki?DoubleBraceInitialization , or simply use Guava:
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
ImmutableMap.of
works for up to 5 entries. Otherwise, use the builder: source.
If you allow 3rd party libs, you can use Guava's ImmutableMap to achieve literal-like brevity:
Map<String, String> test = ImmutableMap.of("k1", "v1", "k2", "v2");
This works for up to 5 key/value pairs, otherwise you can use its builder:
Map<String, String> test = ImmutableMap.<String, String>builder()
.put("k1", "v1")
.put("k2", "v2")
...
.build();
- note that Guava's ImmutableMap implementation differs from Java's HashMap implementation (most notably it is immutable and does not permit null keys/values)
- for more info, see Guava's user guide article on its immutable collection types