Skip to content
Back to posts

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:

  1. Deterministic configuration, such as mapping keys to request URLs.
  2. Unit tests.

Poor uses:

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


Originally published on SegmentFault.

Copyright notice

Unless otherwise stated, quietin owns the copyright in all articles. All rights reserved. Except as permitted by law or with prior written permission, reproduction or republication, in whole or in part, is prohibited. Permitted quotations must credit the author and link to the original article.