I need a multi-threaded Map object to use in my web server's caching, and I need to have null
keys.
HashMap
allows me to have null keys, but ConcurrentHashMap
doesn't. I tried to create a synchronized version of HashMap
using Collections.synchronizedMap(new HashMap())
but it doesn't accept null
keys either.
Is there any alternative that I can use, without having to implement some way to wrap the null
keys?
The Map
returned by Collections.synchronizedMap
supports all of the features of the Map
you give it. If you give it a HashMap
, it supports the null
key (and also null
values, you said "...I need to have "null" key values..." which can be read either way).
This works as expected, for instance:
import java.util.*;
public class MapTest
{
public static final void main(String[] args)
{
Map map;
try
{
map = Collections.synchronizedMap(new HashMap());
map.put("one", "a");
System.out.println("Size = " + map.size());
map.put(null, "b");
System.out.println("Size = " + map.size());
System.out.println("map.get(null) = " + map.get(null));
}
catch (Exception ex)
{
System.out.println("Exception: " + ex.getMessage());
ex.printStackTrace(System.out);
}
System.exit(0);
}
}
Output:
Size = 1 Size = 2 map.get(null) = b
A synchronized map has the issue that, well, it's synchronized. If you can work around the need for null
keys and values, ConcurrentHashMap
would probably be the better option for a server cache. But it "...does not allow null
to be used as a key or value."
Note that you need to manually synchronize the map from synchronizedMap
if you want to iterate. From the JavaDoc:
It is imperative that the user manually synchronize on the returned map when traversing any of its collection views via Iterator, Spliterator or Stream:
...
Failure to follow this advice may result in non-deterministic behavior.
The map handles it for you on get
and such, but not iteration.