This post will discuss various methods to create an immutable map in Java.

Unmodifiable Maps are “read-only” wrappers over other collections. They do not support any modification operations such as add, remove, and clear, but their underlying collection can be changed. Maps that additionally guarantee that no change in the Collection object will ever be visible are referred to as immutable map.

When you don’t expect to modify a collection, it’s a good practice to defensively copy it into an immutable collection. Immutable maps have many advantages over their mutable siblings, like they are thread-safe, more memory-efficient, and can be passed to untrusted libraries without any side effects.

1. Using Guava Library

The Java Collections framework provides the unmodifiableMap() method, but it is unsafe to use as the returned map is only truly immutable if nobody holds a reference to the original collection. The returned map is also inefficient as the data structures will still have all the overhead of mutable collections, including concurrent modification checks, extra space in hash tables, etc.

Guava provides simple, easy-to-use immutable versions of each map using the ImmutableMap class. Unlike Collections’ unmodifiableMap(), an instance of ImmutableMap contains its own private data and will never change. We can create an ImmutableMap collection in several ways:

⮚ Using the copyOf() method

ImmutableMap.copyOf returns an immutable map containing the same entries as a specified map. It returns a NullPointerException if any key or value in the map is null.

Download Code

Output:

java.lang.UnsupportedOperationException
{United States=Washington D.C.}

⮚ Using a Builder

Guava also provides a builder for creating immutable map instances, as shown below:

Download Code

Output:

java.lang.UnsupportedOperationException
{United States=Washington D.C., China=Beijing}

⮚ Using the of() method

ImmutableMap.of() returns an immutable map containing the given entries in order. It throws an IllegalArgumentException if duplicate keys are provided. This works for up to 5 key/value pairs. To create a map with an arbitrary number of entries, we can use Builder’s put() method, which takes key-value pairs instead of a map.

Download Code

Output:

java.lang.UnsupportedOperationException
{United States=Washington D.C.}

2. Collection factory methods (Java 9 and above)

Several collection factory methods have been added in Java 9 that creates a compact, structurally immutable instance of Map. For example,

 
This supports maps up to 10 key-value pairs. There is a no var-args overload of Map.of(), which can handle any number of mappings. To create a map with an arbitrary number of entries, we can use

 
It includes varargs overloads, so there is no fixed limit on the map size. This approach requires each key-value pair to be boxed. For boxing keys and values, we can use

 
Here’s complete usage of this method:

 
As the map is structurally immutable, keys and values cannot be added, removed, or updated from it, but if the contained keys or values are themselves mutable, this may cause the map to behave inconsistently or its contents to appear to change.

That’s all about immutable Map in Java.

 
Reference: Guava’s Wiki – Immutable Collections Explained