I have a handler class that contains a private ConcurrentHashMap which other classes want, but I'm not sure the best way to give it to them.
My apparent options are..
public class StuffHandler { private StuffHandler(){} public static synchronized StuffHandler getInstance() { return INSTANCE; } private final static ConcurrentHashMap<String, Stuff> myStuff = new ConcurrentHashMap<>(); public static ConcurrentHashMap<String, Stuff> getStuff() { return myStuff; } }
There is no such thing as the best way to pass a ConcurrentHashMap
to another class. It all depends on your use case, i.e. on what you want your classes to do.
You have three options:
Return the map as is:
return myStuff;
This will let your other classes modify the actual myStuff
map and everyone will see the changes. However, there won't be any concurrency issue, since ConcurrentHashMap
actually supports concurrent access (hence its name), and it does it in a very efficient way.
Return a copy of the map:
return new HashMap(myStuff);
This returns a fresh new map to every class that calls your getStuff()
method. So every caller can play around with this map, since no one else will see modifications, neither other caller classes nor your StuffHandler
class. Keep in mind that if the map is big, it might result expensive to return a copy every time its getter is called.
Return an unmodifiable view of the map:
return Collections.unmodifiableMap(myStuff);
This does not return a copy of the map. Actually, it doesn't copy anything, but returns a wrapper of your map instead, which doesn't allow modifications. This is transparent to the classes that call getStuff()
. This option returns a live view of the map, so the actual myStuff
map won't be modified (if a modification over the returned map is attempted, an UnsupportedOperationException
will be thrown). Nonetheless, if the actual myStuff
map is modified (by some method of your StuffHandler
class), every other class that has called getStuff()
will see this modification.