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.
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.