Map.merge inserts a non-null value when a key is absent or mapped to null; otherwise, it combines the existing and supplied values with a remapping function. section 8.4
Treat these cases as distinct:
- The remapping function is skipped when the key has no mapping or an existing null mapping. section 8.4
- A non-null existing value invokes the function with the old and new values. section 8.4
- A null result from the function removes the mapping. section 8.4
- A null value argument is not accepted and causes NullPointerException; merge does not write a null mapping. section 8.4
Null mappings change the apparent control flow
With map.put("x", null), map.merge("x", "1", (x, y) -> null) stores "1" without calling the function. A second merge calls the function, receives null, and deletes the entry. Passing null as the value argument instead throws NullPointerException. section 8.4
Atomic occurrence counting
For a concurrently updated map, replace a get-and-put sequence with map.merge(key, 1, Integer::sum). This performs the increment atomically when the concurrent map implementation provides the required operation. section 9.12
Table 8.2 Behavior of java.util.Map interface methods with respect to null
|
java.util.Map interface method
|
Distinguishes between existing null mapping and no mapping at all?
|
Puts null mapping if the value parameter is null?
|
Removes existing mapping if lambda returns null?
|
|---|---|---|---|
containsKey
|
yes
|
—
|
—
|
getOrDefault
|
yes
|
—
|
—
|
get
|
no
|
—
|
—
|
put
|
no
|
yes
|
—
|
putIfAbsent
|
no
|
yes
|
—
|
compute
|
no
|
—
|
yes
|
computeIfPresent
|
no
|
—
|
yes
|
computeIfAbsent
|
no
|
—
|
no
|
merge
|
no
|
no
|
yes
|
Compare Map methods by whether they distinguish null mappings, accept null values, and remove mappings after a null function result. section 8.4
