Java 8 introduced new way to obtain a concurrent Set
implementation
// Pre-Java-8 way to create a concurrent set
Set oldStyle = Collec
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.
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 Set
s 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…