The result of an initialized HashMap is a mutable map or an immutable map:

  • Mutable map : in this case we can modify the Map entries.
  • Immutable map : in this case we can’t add or modify the Map entries, and if we modify it, it throws UnsupportedOperationException.

To initialize a HashMap , there are many ways :

1. The Standard way:

// normal way, mutable map
  Map<String, String> map = new HashMap<>();
  map.put("key1", "value1");
  map.put("key2", "value2");
  map.put("key3", "value3");
  System.out.println(map.getClass());             // java.util.HashMap

  // convert mutable Map to immutable map
  Map<String, String> immutableMap = Collections.unmodifiableMap(map);
  System.out.println(immutableMap.getClass());    // java.util.Collections$UnmodifiableMap
  immutableMap.put("key4", "value4");             // UnsupportedOperationException

2. Using Collections.singletonMap

In this example we will use Collections.singletonMap to initialize a single entry SingletonMap, witch give an immutable map.

  // @since 1.3
  // single entry immutable map
  Map<String, String> map = Collections.singletonMap("key1", "value1");

  System.out.println(map.getClass());   // java.util.Collections$SingletonMap
  map.put("key2", "value2");            // throws UnsupportedOperationException

3. In Java 9 by using Map.of

Java 9 introduced a new way to initialize a HashMap , Map.of returns an immutable map containing up to 10 entries.

 // Java 9, max is 10 entries or elements, immutable map
  Map<String, String> map = Map.of(
      "key1", "value1",
      "key2", "value2",
      "key3", "value3"
  );

  System.out.println(map.getClass());   // java.util.ImmutableCollections$MapN
  map.put("key3", "value4");            // throws UnsupportedOperationException

Review the Java 9 source code of Map.java. They created 10 Map.of overloading methods to initialize a Map containing up to 10 entries or elements.

  static <K, V> Map<K, V> of(K k1, V v1) {
    return new ImmutableCollections.Map1<>(k1, v1);
  }

  static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2) {
    return new ImmutableCollections.MapN<>(k1, v1, k2, v2);
  }

  static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
      return new ImmutableCollections.MapN<>(k1, v1, k2, v2, k3, v3);
  }

  // up to 10 elements...

4. Java 9 Map.ofEntries

Java 9 introduced a similar API, Map.ofEntries, which returns an unmodifiable or immutable map, but this Map has no limit of the Map entry, and we can create as many entries as we want.

// Java 9, no limit of Map entry, immutable map.
  Map<String, String> map = Map.ofEntries(
      Map.entry("key1", "value1"),
      Map.entry("key2", "value2"),
      Map.entry("key3", "value3")
  );

  System.out.println(map.getClass());    // java.util.ImmutableCollections$MapN
  map.put("key4", "value4");             // throws UnsupportedOperationException

5. Create a function to return a Map

We can create a function to initialize a HashMap, which works for all Java versions. The function returns a mutable map.


  // It works for all Java versions, mutable map.
  Map<String, String> map = createMap();

  System.out.println(map.getClass()); // java.util.HashMap
  map.put("key4", "value4");          // yes, we can do it

  private static Map<String, String> createMap() {
      Map<String, String> map = new HashMap<>();
      map.put("key1", "value1");
      map.put("key2", "value2");
      map.put("key3", "value3");
      return map;
  }

6. Static Initializer

This solution is for a static Map variable, and it returns a mutable map.

  public static Map<String, String> map;
  static {
      // mutable map
      map = new HashMap<>();
      map.put("key1", "value1");
      map.put("key2", "value2");
      map.put("key3", "value3");
  }

7. Java 8, Stream of SimpleEntry

This example creates a stream of SimpleEntry and returns a mutable map. Do not use the below method to initialize a HashMap, I don’t see any benefits of a stream of SimpleEntry, error-prone and ugly syntax, just for reference.

import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toMap;
//...

  // mutable map
  Map<String, String> map = Stream.of(
          new AbstractMap.SimpleEntry<>("key1", "value1"),
          new AbstractMap.SimpleEntry<>("key2", "value2"),
          new AbstractMap.SimpleEntry<>("key3", "value3"))
          .collect(
                  toMap(AbstractMap.SimpleEntry::getKey,
                          AbstractMap.SimpleEntry::getValue)
          );
  System.out.println(map.getClass()); // java.util.HashMap
  map.put("key4", "value4");          // no problem.
Tagged:

Laisser un commentaire