Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConcurrentHashMap.newKeySet() vs Collections.newSetFromMap()

Java 8 introduced new way to obtain a concurrent Set implementation

// Pre-Java-8 way to create a concurrent set
Set<String> oldStyle = Collections.newSetFromMap(new ConcurrentHashMap<>());
// New method in Java 8
Set<String> newStyle = ConcurrentHashMap.newKeySet();

Is there any reason to prefer new method?

Any advantages/disadvantages?

like image 726
turbanoff Avatar asked Aug 17 '15 15:08

turbanoff


People also ask

Why ConcurrentHashMap is faster than HashMap?

HashMap performance is relatively high because it is non-synchronized in nature and any number of threads can perform simultaneously. But ConcurrentHashMap performance is low sometimes because sometimes Threads are required to wait on ConcurrentHashMap.

What is the use of ConcurrentHashMap () in multithreading?

ConcurrentHashMap class is thread-safe i.e. multiple threads can operate on a single object without any complications. At a time any number of threads are applicable for a read operation without locking the ConcurrentHashMap object which is not there in HashMap.

Why there is no concurrent Hashset in Java?

There's no built in type for ConcurrentHashSet because you can always derive a set from a map. Since there are many types of maps, you use a method to produce a set from a given map (or map class). In Java 8 (pointed out by @Matt), you can get a concurrent hash set view via ConcurrentHashMap. newKeySet() .

Can multiple threads read ConcurrentHashMap at the same time?

ConcurrentHashMap is divided into different segments based on concurrency level. So different threads can access different segments concurrently in java. Can threads read the segment of ConcurrentHashMap locked by some other thread in java? Yes.


2 Answers

ConcurrentHashMap.newKeySet() is just a part of a feature which is much broader than Collections.newSetFromMap(new ConcurrentHashMap<>()).

The difference becomes clear if you look at this example:

Set<String> set=new ConcurrentHashMap<String,String>().keySet("hello");

Instead of mapping to Boolean.TRUE you are now adding the value "hello" when adding a new value to the Set.

That’s why the returned Sets have the type ConcurrentHashMap.KeySetView. This type has additional methods for asking for the backing map as well as which value will be used when adding new keys.


So while ConcurrentHashMap.newKeySet() looks like doing the same as Collections.newSetFromMap(new ConcurrentHashMap<>()), there is the semantic difference that the latter says you shouldn’t use the map afterwards while the former is part of a feature which is designed to interact with the map.

See Collections.newSetFromMap:

The specified map must be empty at the time this method is invoked, and should not be accessed directly after this method returns.

In fact, it is not even specified that Collections.newSetFromMap will use Boolean.TRUE for added values—you should never deal with that anyway…


It might also be useful when you wan to pass the Set to code which explicitly requests a ConcurrentHashMap.KeySetView.


If you are using the result using the compile-time type Set only, there is still the possibility that code which receives that Set will use instanceof/type casts to find out that the result of ConcurrentHashMap.newKeySet() is backed by a ConcurrentHashMap while the result of Collections.newSetFromMap won’t tell you. On the other hand, that also allows code to do unintended things with backing map that way…

like image 187
Holger Avatar answered Oct 19 '22 18:10

Holger


ConcurrentHashMap.newKeySet() should be somewhat more efficient as removes a single level of indirection. Collections.newSetFromMap(map) is mostly based on redirecting the operations to the map.keySet(), but ConcurrentHashMap.newKeySet() is very close to map.keySet() itself (just with additions support).

As for functionality, I see no difference.

like image 12
Tagir Valeev Avatar answered Oct 19 '22 18:10

Tagir Valeev