UnmodifiableMap (Java Collections) vs ImmutableMap (Google)

139,487

Solution 1

An unmodifiable map may still change. It is only a view on a modifiable map, and changes in the backing map will be visible through the unmodifiable map. The unmodifiable map only prevents modifications for those who only have the reference to the unmodifiable view:

Map<String, String> realMap = new HashMap<String, String>();
realMap.put("A", "B");

Map<String, String> unmodifiableMap = Collections.unmodifiableMap(realMap);

// This is not possible: It would throw an 
// UnsupportedOperationException
//unmodifiableMap.put("C", "D");

// This is still possible:
realMap.put("E", "F");

// The change in the "realMap" is now also visible
// in the "unmodifiableMap". So the unmodifiableMap
// has changed after it has been created.
unmodifiableMap.get("E"); // Will return "F". 

In contrast to that, the ImmutableMap of Guava is really immutable: It is a true copy of a given map, and nobody may modify this ImmutableMap in any way.

Update:

As pointed out in a comment, an immutable map can also be created with the standard API using

Map<String, String> immutableMap = 
    Collections.unmodifiableMap(new LinkedHashMap<String, String>(realMap)); 

This will create an unmodifiable view on a true copy of the given map, and thus nicely emulates the characteristics of the ImmutableMap without having to add the dependency to Guava.

Solution 2

Have a look at ImmutableMap JavaDoc: doc

There is information about that there:

Unlike Collections.unmodifiableMap(java.util.Map), which is a view of a separate map which can still change, an instance of ImmutableMap contains its own data and will never change. ImmutableMap is convenient for public static final maps ("constant maps") and also lets you easily make a "defensive copy" of a map provided to your class by a caller.

Solution 3

ImmutableMap does not accept null values whereas Collections.unmodifiableMap() does. In addition it will never change after construction, while UnmodifiableMap may. From the JavaDoc:

An immutable, hash-based Map with reliable user-specified iteration order. Does not permit null keys or values.

Unlike Collections.unmodifiableMap(java.util.Map), which is a view of a separate map which can still change, an instance of ImmutableMap contains its own data and will never change. ImmutableMap is convenient for public static final maps ("constant maps") and also lets you easily make a "defensive copy" of a map provided to your class by a caller.

Solution 4

Guava Documentation

The JDK provides Collections.unmodifiableXXX methods, but in our opinion, these can be unwieldy and verbose; unpleasant to use everywhere you want to make defensive copies unsafe: the returned collections are only truly immutable if nobody holds a reference to the original collection inefficient: the data structures still have all the overhead of mutable collections, including concurrent modification checks, extra space in hash tables, etc.

Share:
139,487

Related videos on Youtube

John Humphreys
Author by

John Humphreys

I'm a cloud DevOps director with a strong history of software &amp; service development spanning military embedded systems, financial platforms, big data metrics systems, and general DevOps platform services. For the last 6+, years I have focused on building cross-company platform SaaS &amp; PaaS services spanning query, orchestration, monitoring and compute both in the cloud and on-premises. I have led significant efforts leveraging orchestration technologies (Kubernetes, Airflow), big data technologies (Apache Spark, Presto, Apache Drill, Hive, Data Lakes), and streaming technologies (e.g. Kafka / Messaging). I have driven DevOps and CI/CD practices, improving automation and decreasing release cycle duration repeatedly (leveraging kubernetes, GitLab, terraform, ansible, etc). I've led DevOps teams managing large scale infrastructure and services in both the Azure and AWS clouds, but am much more accustomed to working in AWS these days. I also keep a blog here -&gt; https://coding-stream-of-consciousness.com. It is mostly to help me recall things in the future; but I like that it occasionally saves others time as well. I hope you find it useful.

Updated on July 08, 2022

Comments

  • John Humphreys
    John Humphreys almost 2 years

    Context

    I need to return a reference to a map that I'm using for a data cache, and I'd like to make sure nobody can modify their reference.

    Question

    I've seen lots of references to UnmodifiableMap and ImmutableMap online, but I don't see anything comparing/contrasting them. I figure there is a good reason that Google/Guava created their own version - can someone tell me what it is?

    • Jimmy
      Jimmy about 10 years
    • John Humphreys
      John Humphreys about 10 years
      Apparently my Google terms sucked. I'll accept the first answer when the clock rolls over since they're all the same :).
  • Martin Nielsen
    Martin Nielsen about 10 years
    1up for not just linking to the documentation, but providing an example as well.
  • John Humphreys
    John Humphreys about 10 years
    Good example, thank you for the help :).
  • user2045474
    user2045474 about 8 years
    very nice explanation
  • Lorkenpeist
    Lorkenpeist over 7 years
    It's worth noting that a truly immutable copy of the original backing map can be achieved with Map<String, String> unmodifiableMap = Collections.unmodifiableMap(new HashMap<>(realMap)); Achieves the same result as ImmutableMap without the dependency on third party libraries.
  • Marco13
    Marco13 over 7 years
    @Lorkenpeist Good point. In practice, I would recommend Collections.unmodifiableMap(new LinkedHashMap<>(realMap)); to keep the iteration order intact (but there may be cases where this doesn't matter). In any case, I'm regularly doing this, and would prefer it over ImmutableMap (particularly if Guava is not already a dependency anyhow). There may be justifications for still using ImmutableMap (e.g. using it as a return type, to show in an interface that the returned map is immutable, but one cannot make a general recommendation here)
  • Steph
    Steph over 5 years
    Now with Java 9, you can use: Map<String,String> unmodifiableMap = Map.ofEntries(entry("A","B"), entry("C","D"), entry("E","F")); which is more beautiful to my mind
  • David Conrad
    David Conrad over 5 years
    The link has died.
  • FrankyFred
    FrankyFred almost 5 years
  • Jany
    Jany over 4 years
    Immutable map is only useful if you are setting up static config but IMO there are much better patterns to encapsulate the same. Also Map is truly immutable if both value and keys are immutable. Immutable map wont protect in case value returned is mutable. In most of the use case Collections.unmodifiable map should suffice, again not a good pattern to return raw maps for any function invocation.