Joker
Joker

Reputation: 11146

How to convert Collections.synchronizedMap(new HashMap()) to Hash Map

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

Answers (3)

yshavit
yshavit

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

jpkroehling
jpkroehling

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

Rahman
Rahman

Reputation: 3785

Will it be ok :

        Map hashMap = new HashMap();
        Map syncMap = Collections.synchronizedMap(hashMap);
        HashMap m = new HashMap(syncMap);

Upvotes: 0

Related Questions