How to Directly Initialize a Hashmap (In a Literal Way)

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;
}

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

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.

Literal declaration of HashMap in Java

Though {{ (double brace) is an anti pattern, something like this you can write

HashMap<String, String> map = new HashMap<String, String>(){{
put("Key 1", "Value 1");
put("Key 2", "Value 2");
put("Key 3", "Value 3");
}};

Edit :

If you are looking for a better way to put elements, iterate over your json and put key values in a loop.

How can I initialise a static Map?

The instance initialiser is just syntactic sugar in this case, right? I don't see why you need an extra anonymous class just to initialize. And it won't work if the class being created is final.

You can create an immutable map using a static initialiser too:

public class Test {
private static final Map<Integer, String> myMap;
static {
Map<Integer, String> aMap = ....;
aMap.put(1, "one");
aMap.put(2, "two");
myMap = Collections.unmodifiableMap(aMap);
}
}

Java - instantiate a hashmap from literal value pairs

Since you are using Java 8 you can use streams and collectors to achieve this.

import java.util.AbstractMap.SimpleEntry;
import java.util.stream.Collectors;
import java.util.stream.Stream;

...

Map<String, String> map = Stream.of(
new SimpleEntry<>("key1", "value1"),
new SimpleEntry<>("key2", "value2"))
.collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue));

It is pretty verbose but has a substantial advantage over the static initialisation method - the class which instantiates the map this way is not referenced by it. In the case of static initialisation the anonymous class created with new HashMap<>(){...} will hold a reference to the class that created it and the latter cannot be garbage collected until the map itself is.

HashMap initialization in java

Yes it is possible:

public static <K,V> Map<K,V> mapFromArrays(K[] keys,V[]values){
HashMap<K, V> result=new HashMap<K, V>();
for(int i=0;i<keys.length;i++){
result.put(keys[i], values[i]);
}
return result;

}

Assuming that keys and values have the same length.

You may also use this function in a static initializer like this:

private static Integer[] keys=new Integer[]{1,2,3};
private static String[] values=new String[]{"first","second","third"};

private static Map<Integer,String> myMap;
{
myMap=mapFromArrays(keys, values);
}

Correct way to initialize HashMap and can HashMap hold different value types?

It really depends on what kind of type safety you need. The non-generic way of doing it is best done as:

 Map x = new HashMap();

Note that x is typed as a Map. this makes it much easier to change implementations (to a TreeMap or a LinkedHashMap) in the future.

You can use generics to ensure a certain level of type safety:

Map<String, Object> x = new HashMap<String, Object>();

In Java 7 and later you can do

Map<String, Object> x = new HashMap<>();

The above, while more verbose, avoids compiler warnings. In this case the content of the HashMap can be any Object, so that can be Integer, int[], etc. which is what you are doing.

If you are still using Java 6, Guava Libraries (although it is easy enough to do yourself) has a method called newHashMap() which avoids the need to duplicate the generic typing information when you do a new. It infers the type from the variable declaration (this is a Java feature not available on constructors prior to Java 7).

By the way, when you add an int or other primitive, Java is autoboxing it. That means that the code is equivalent to:

 x.put("one", Integer.valueOf(1));

You can certainly put a HashMap as a value in another HashMap, but I think there are issues if you do it recursively (that is put the HashMap as a value in itself).

HashMap cant be initialized with loop? Initialize HashMap from textfile

As stated in the comments, you should be using a new instance of ArrayList each time you determine the key has changed, otherwise you are simply re-using the same ArrayList for EVERY key

The following example demonstrates a modified version of your code, so that when the code detects a new key, and the previous key is not blank, it will map the key to the current instance of the ArrayList.

It will then create a new instance of an ArrayList and place all the preceeding values into it

File file = new File(System.getProperty("user.dir") + "/data.txt");
Map<String, List<String>> map = new HashMap<String, List<String>>();

try (Scanner scan = new Scanner(file);) {
String key = "";
List<String> value = new ArrayList<String>();

while (scan.hasNextLine()) {
String line = scan.nextLine();

if (line.contains("!")) {
if (!key.trim().isEmpty()) {
map.put(key, value);
System.out.println(key + " , " + value);
}
key = line;
key = key.replaceAll("!", "");
value = new ArrayList<String>();
} else {
value.add(line);
}

}
if (!key.trim().isEmpty() && !value.isEmpty()) {
map.put(key, value);
}

scan.close();

System.out.println(map.get("first")); //This prints the second category
System.out.println(map.get("second"));
} catch (Exception e) {
e.printStackTrace();
}


Related Topics



Leave a reply



Submit