ConcurrentHashMap putIfAbsent() is returning null
Solution 1
ConcurrentMap.putIfAbsent
returns the previous value associated with the specified key, or null if there was no mapping for the key. You did not have a value associated with "key 3". All correct.
NOTE: Not just for ConcurrentMap
, this applies to all implementations of Map
.
Solution 2
Problem is that by definition putIfAbsent return old value and not new value (old value for absent is always null). Use computeIfAbsent - this will return new value for you.
private static String get(final String key) {
return map.computeIfAbsent(key, s -> "value 3");
}
Solution 3
putIfAbsent()
returns the previous value associated with the specified key, or null
if there was no mapping for the key, and because key 3
is not present in the map so it returns null
.
You have added key 1
and key 2
in the map but key 3
is not associated with any value. So you get a null
. Map key 3
with some value and putIfAbsent()
will return previous value associated with that key.
Like if map already contained key 3
associated with value A
key 3 ---> A
Then on calling map.putIfAbsent("key 3","B")
will return A
Solution 4
This is a frequently asked question, which perhaps suggest this behaviour is unintuitive. Maybe the confusion comes from the way dict.setdefault() works in python and other languages. Returning the same object you just put helps cut a few lines of code.
Consider:
if (map.contains(value)){
obj = map.get(key);
}
else{
obj = new Object();
}
versus:
obj = map.putIfAbsent(key, new Object());
Solution 5
It's in the javadoc:
returns the previous value associated with the specified key, or null if there was no mapping for the key
Related videos on Youtube
Comments
-
Niranjan over 1 year
The following program is printing
null
. I am not able to understand why.public class ConcurrentHashMapTest { public static final ConcurrentMap<String, String> map = new ConcurrentHashMap<>(5, 0.9f, 2); public static void main(String[] args) { map.putIfAbsent("key 1", "value 1"); map.putIfAbsent("key 2", "value 2"); String value = get("key 3"); System.out.println("value for key 3 --> " + value); } private static String get(final String key) { return map.putIfAbsent(key, "value 3"); } }
Could someone help me understand the behavior?
-
Jon Skeet about 10 yearsWhat behaviour did you expect, and why?
-
-
Mark Rotteveel about 10 yearsFor quotes you should use
>
, not the code formatting. -
Bozho about 10 yearsYeah, I forgot... :) haven't answered for a awhile
-
Jerry Chin over 5 yearsit doesn't allow exception throwing, too bad.
-
Ondřej Stašek over 5 yearsAs any other lambda. So either use @SneakyThrows or rethrow exception as RuntimeException.
-
nurettin over 5 yearsIs this an atomic operation? As in, can the map change between contains and get?
-
Frans almost 4 years
@SneakyThrows
is evil. -
Ondřej Stašek almost 4 yearschecked exceptions are far more evil than @SneakyThrows :)