ImmutableMap Does Not Allow null
An explanation of Guava ImmutableMap's null restrictions and the tradeoffs of alternative immutable map wrappers.
Example
I found code like this in a project:
Map tmpParams = ImmutableMap.of( "extraInfos", ext.get("extraInfos"), "otherParams", ImmutableMap.builder() .put("version", 0) .put("orderId", MapUtils.getString(ext, "orderId"));It occasionally raised an NPE because the value associated with orderId was null. ImmutableMap permits neither null keys nor null values.
Guava’s GitHub repository has a discussion of null values. The official recommendation is to wrap them with Optional; avoiding null also makes inline and stream operations easier. Other Guava components, including LoadingCache, likewise reject null.
If you need an immutable map that permits null, you can use:
Map<String, String> testMap = new HashMap<>();testMap.put("a", "1");
Map<String, String> immutableMap = Collections.unmodifiableMap(new HashMap<>(testMap));Keys and values cannot be replaced through this map, although fields inside a mutable value object can still be changed.
Summary
Good uses for ImmutableMap:
- Deterministic configuration, such as mapping keys to request URLs.
- Unit tests.
Poor uses:
- Unknown keys or values that may be
null.
One practical point
With a HashMap, this code would not have failed. Tool classes have their own constraints; if you do not know them, cases like this can be surprising.