Reputation: 11146
We have a Interface that returns HashMap .
Now due to thread safty we have synchronized our Map using
Collections.synchronizedMap(new HashMap());
Now clients that are using our Interface facing class cast exception since
Collections.synchronizedMap returns a synchronized map and which can not be cast to hash Map
We have to convert this synchronizedMap back to hash map
Is there any way to convert synchronizedMap returned by
Collections.synchronizedMap() back to hash map.
Upvotes: 0
Views: 1222
Reputation: 43391
If copying is acceptable (that is, you don't need subsequent writes to the synchronized map to be reflected in the returned map), just use HashMap's constructor that takes a Map input. Make sure to synchronize on the synchronizedMap first, since the copy requires iteration over the map (which must anyways be synchronized).
synchronized (map) {
return new HashMap<>(map);
}
The synchronized block is not really optional. From the docs:
It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views
Upvotes: 3
Reputation: 14061
Not perfect, but perhaps it could work in your case: create a class that extends HashMap, but that internally has a synchronized Map. Then, delegate all method calls to your internal map. On the constructors, create a new HashMap, then synchronize it. Something like this:
public class SynchronizedHashMap<K, V> extends HashMap<K, V> {
private Map<K, V> internalMap;
public SynchronizedHashMap(int initialCapacity, float loadFactor) {
internalMap = Collections.synchronizedMap(new HashMap<>(initialCapacity, loadFactor));
}
public SynchronizedHashMap(int initialCapacity) {
internalMap = Collections.synchronizedMap(new HashMap<>(initialCapacity));
}
public SynchronizedHashMap() {
internalMap = Collections.synchronizedMap(new HashMap<>());
}
public SynchronizedHashMap(Map<? extends K, ? extends V> m) {
internalMap = Collections.synchronizedMap(new HashMap<>(m));
}
@Override public int size() {
return internalMap.size();
}
@Override public boolean isEmpty() {
return internalMap.isEmpty();
}
@Override public boolean containsKey(Object o) {
return internalMap.containsKey(o);
}
...
}
And remember, that's why you should be coding for interfaces, not to concrete implementations. Your interface should return a Map, and your client should consume a Map, without knowledge about which Map it is.
Upvotes: 1
Reputation: 3785
Will it be ok :
Map hashMap = new HashMap();
Map syncMap = Collections.synchronizedMap(hashMap);
HashMap m = new HashMap(syncMap);
Upvotes: 0