Card 07/ 09

GotchaDifficulty: Advanced1 min

Why a null Key Is Fine in One Map and Fatal in Another

Code that has worked for two years throws the first time somebody swaps a HashMap for a TreeMap to get sorted output. The only change was the word after new.

java
Map<String, Integer> sorted = new TreeMap<>();
sorted.put(null, 1);
text
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Comparable.compareTo(Object)" because "k1" is null

A HashMap handles a null key as a special case and stores it in the first bucket. A TreeMap has to compare the key against the ones already there, and there is nothing sensible to compare null with, so it refuses.

Which maps accept null keys and null values
ClassNull keyNull values
HashMapOneAny number
LinkedHashMapOneAny number
TreeMapNo — throwsAny number
ConcurrentHashMapNo — throwsNo — throws
Map.of(...)No — throwsNo — throws

Keep null out of maps as a habit rather than checking the table each time. A key that might be missing is what getOrDefault is for, and a value that might not exist is what Optional is for.