Collections.newSetFromMap(»ConcurrentHashMap«) vs. Collections.synchronizedSet(»HashSet«)

What you may be thinking of is

Set<Type> set = Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());

This supports concurrent updates and reads. Its Iterator won't throw ConcurrentModicationException. where as

Set<Type> set = Collections.synchronizedSet(new HashSet<Type());

Is more light weight but only allows one thread at a time to access the set. You need to lock the set explicitly if you want to Iterator over it and you can still get a CME if you don't update it in a safe way (while iterating over it)


The first one returns a Set that basically has the same thread-safe and performance guarantees as the map passed as argument. If the map isn't thread-safe, the set won't be either. You typically use this method to create a concurrent set from a concurrent map, because there is no ConcurrentHashSet in the API.

The second one returns a proxy to the given set, which has all its methods synchronized.


Actually you may get several Set thread-safe implementations.

I. Collections.synchronizedSet(new HashSet

I would not recommend this solution. It is itself thread-safe, must still be used with care in a concurrent environment. See:

Stack stack = new SynchronizedArrayStack(new ArrayStack());
...
// don't do this in a multi-threaded environment
if (!stack.isEmpty()) {
  stack.pop();              // can throw IllegalStateException
}

As a result you must use client-side locking:

synchronized(stack) {
  if (!stack.isEmpty()) {
    stack.pop();
  }
}

II. The second alternative concurrent implementation of Set interface - CopyOnWriteArraySet. However this solution should not be used in a context where you were expecting many searches or insertions. But iteration costs O(1) per element faster than HashSet and it has one advantage which is really compelling in some applications.

III. The last one uses the implementation of CuncurrentHashMap:

Collections.newSetFromMap(new ConcurrentHashMap<Type, Boolean>());

It uses implementations of java.util.concurrent.locks.Lock. The map divides itself into parts that can be separately locked, giving improved concurrency. So you should choose between the last two options.

Thera are also options for sorted set impelementations. I would recommend you to read Java Generics and Collections chapter 11.5 Collections and Thread Safety.