Map.of() and Map.ofEntries() methods in Java
This post will discuss about Map.of()
and Map.ofEntries()
methods in Java.
1. Using Map.of()
method
Java 9 made it very convenient to create instances of the map by providing static factory methods on the Map
interface that creates a compact, unmodifiable instance of Map. For example, the Map.of()
method allows us to create an immutable map with up to 10
key-value pairs. The syntax is:
Map.of(k1, v1) // creates a singleton map
Map.of(k1, v1, k2, v2)
Map.of(k1, v1, k2, v2, k3, v3)
…
Map.of(k1, v1, k2, v2, k3, v3, …, k10, v10)
Here, k
is the type of keys and v
is the type of values. The resulting map will be an immutable map, which means that we cannot modify it by adding, removing, or updating its elements. If we try to do so, we will get an UnsupportedOperationException
. For example, to create an immutable map of countries and continents, we can write:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.util.Map; class Main { public static void main(String[] args) { Map<String, String> immutableMap = Map.of("India", "Asia", "France", "Europe", "Brazil", "South America"); // {Brazil=South America, India=Asia, France=Europe} System.out.println(immutableMap); try { // updating any key will result in java.lang.UnsupportedOperationException immutableMap.put("Germany", "Europe"); } catch (UnsupportedOperationException ex) { System.out.println("Cannot modify an immutable map"); } } } |
2. Using Map.ofEntries()
method
There is a no var-args overload of Map.of()
which can handle any number of mappings. To create an immutable map with an arbitrary number of entries, we can use Map.ofEntries()
method with Map.Entry
objects as arguments. It includes varargs overloads, so there is no fixed limit on the map size. This method requires each key-value pair to be boxed. We can use the Map.entry()
method to create a Map.Entry
object from a key and a value. Here’s the syntax:
entry(k1, v1),
entry(k2, v2),
entry(k3, v3),
// …
entry(kn, vn)
);
Like before, the resulting map will be an immutable map, which means we will get an UnsupportedOperationException
if we try to do modify it. For example, to create an immutable map of fruits and their colors, we can write:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import java.util.Map; class Main { public static void main(String[] args) { Map<String, String> immutableMap = Map.ofEntries( Map.entry("Strawberry", "Red"), Map.entry("Blueberry", "Blue"), Map.entry("Papaya", "Green") ); // {Blueberry=Blue, Papaya=Green, Strawberry=Red} System.out.println(immutableMap); } } |
The main difference between Map.of()
and Map.ofEntries()
methods is that Map.of()
takes a fixed number of key-value pairs as arguments, while Map.ofEntries()
takes a variable number of Map.Entry
objects as arguments. Both these methods return an instance of the Map
interface, and not a specific implementation class. Therefore, we should not make any assumptions about the identity or performance of the returned maps.
3. Characteristics of Map.of()
and Map.ofEntries()
methods
The map instances created by the Map.of()
and Map.ofEntries()
methods have the following characteristics:
- They are structurally immutable. Keys and values cannot be added, removed, or updated. Any attempt to do so will throw an
UnsupportedOperationException
. However, if the contained keys or values are mutable, this may cause the map to behave inconsistently, or its contents appear to change. - They do not allow
null
keys or values. Any attempt to use anull
key or value will throw aNullPointerException
. - They are serializable if all keys and values are serializable.
- If we pass duplicate keys to a static factory method, they will not be accepted when the map is created. An
IllegalArgumentException
will be thrown instead. - They have an unspecified iteration order of the mappings, which may change across different implementations or invocations.
- The returned instances are based on their values, not their identities. Callers should not expect that the same instance will be returned every time. Factories can either create new instances or use existing ones. So, operations that depend on the identity of the instances (such as reference equality (==), getting their identity hash code, or synchronizing them) are not trustworthy and should not be used.
- They are optimized for performance and memory usage, depending on the number and type of the key-value pairs.
4. Create a Mutable Copy
To create a mutable map from the immutable map, we can use a constructor or a copy method of a concrete map implementation, such as HashMap or LinkedHashMap. For instance:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import java.util.HashMap; import java.util.Map; class Main { public static void main(String[] args) { Map<String, String> map = new HashMap<>(Map.of("India", "Asia", "France", "Europe")); map.put("Brazil", "South America"); // {France=Europe, Brazil=South America, India=Asia} System.out.println(map); } } |
Also note that static factory methods on concrete collection classes such as HashMap
are not included in Java 9. Since static methods on interfaces are not inherited, it will not be possible to invoke them via an implementing class nor an instance of the interface type.
Reference: JEP 269: Convenience Factory Methods for Collections
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)