How to use ConcurrentHashSet from ConcurrentHashMap in Java 8 - Example Tutorial

There is no ConcurrentHashSet in JDK 8, but you can still create one for yourself using the ConcurrentHashMap class of java.util. Concurrent package. A new method is added into ConcurrentHashMap in JDK 8, newKeySet(), which allows you to create a concurrent hash set backed by a concurrent hash map. If you remember, whenever you get keys from the map, they are returned in a Set e.g. for the old keySet() method, because the map only has unique keys. Since the map doesn't allow duplicate keys, it can be used as a set, as long as you only care for keys or just one element. 

That's why Java designers are added the newKeySet() method to convert a map to set. This is also a static method, which means you don't need a ConcurrentHashMap object to create a concurrent hash set.

The Set returned by the keySet() method is backed by a ConcurrentHashMap with given keys and values are always Boolean.TRUE. It is also overloaded to accept initial capacity to avoid internal re-sizing. If you know, the HashSet class also internally uses a HashMap where values are always the same, an object, which is possible because Map allows duplicate values.

Unlike the List returned by Arrays.asList(), which doesn't allow you to add or remove elements, the Set returned by newKeySet() is like any normal Set implementations and allows you to add, remove or perform any other Set operation. 

You can even pass this Set to a method which is accepting a Set interface as a parameter. I'll show this in the coming example.




Java Program to create ConcurrentHashSet

Here is our Java program to demonstrate how you can generate a ConcurrentHashSet in JDK 8 by using the newKeSet() method added into java.util.concurrent.ConcurrentHashMap class. 

Even though I have used an object of the concurrent hash map here, it's not required because unlike keySet(), the newKeySet() is a static method.

Let's the code to actually generate a concurrent hash set in Java 8:

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/*
 * Java Program to create ConcurrentHashSet from ConcurrentHashMap
 * This code requires JDK 8 because we use newKeySet() method
 * which is only available in ConcurrentHashMap class from JDK 8. 
 */
public class Demo {

  public static void main(String[] args) throws Exception {

    // step 1 - create a concurrent hashmap (optional)
    ConcurrentHashMap<String, Integer> wordLengh = new ConcurrentHashMap<>();

    // step 2 - create a set from map by using newKeySet() method
    // provide size to prevent resizing and better performance
    Set<String> words = ConcurrentHashMap.newKeySet(wordLengh.size());

    // step 3 - you can add elements into set
    words.add("Java");
    words.add("JavaScript");

    // step 4 - you can remove elements from set
    words.remove("JavaScript");

    // step 5 - you can also pass this set to any method expecting set
    System.out.println(words);

  }

}

Output:
[Java]

You can see that you can easily add and remove elements from the Set returned by the newKeySet() method. As I said, the Set is backed by ConcurrentHashMap, which means multiple readers can retrieve values simultaneously. 

Also, multiple writers can insert values into the set without blocking until the read and write operation occurs in the same segment. You can also see Java Fundamentals: Collections to learn more about the internal implementation of various collection classes of Java API.


Btw, If you remember, a concurrent hash map never locks the whole map. Instead, it divides the map into several segments, by default 16, also knowns as concurrency level, and only locks the segment where modification is happening. This means multiple writes are possible if they are happening at different segments.

Btw, the concurrent hash set is not only a thread-safe set that is available in JDK, you have some more choices e.g. you can use CopyOnWriteArraySet, which is similar to CopyOnWriteArrayList i.e. it copies the whole collection into a new one whenever a write happens but because of a this behavior, they are only useful for a set with a small number of elements with infrequent write. 

You can further read the Java: A Beginners Guide 6th Edition for more details on concurrent collection classes.

How to create ConcurrentHashSet from ConcurrentHashMap in Java 8 - Example Tutorial


That's all about how to convert ConcurrentHashMap to ConcurrentHashSet in Java. This is a nice little tip that allows you to use a map as Set with all the concurrency benefits provided by a concurrent hash map without any extra effort. The newKeySet() is like any static factory method, which you can invoke with the class name without even needing a ConcurrentHashMap object.


Other Java Collection tutorials you may like
  • How HashMap internally works in Java? (answer)
  • What is the difference between HashSet, TreeSet, and LinkedHashSet in Java? (answer)
  • 10 Java HashMap based Interview Questions with Answers (list)
  • What is the difference between HashMap and LinkedHashMap in Java? (answer)
  • How to sort a Map by values in Java 8? (tutorial)
  • How to sort an ArrayList using Comparator in Java 8? (tutorial)
  • What is the difference between Iterator and ListIterator in Java? (answer)
  • How to remove elements from HashMap during iteration in Java? (answer)

Thanks for reading this article; if you like this article, please share it with your friends and colleagues. If you have any question or feedback then please drop a comment.

Now, is the quiz time, what is difference between TreeSet and LinkedHashSet in Java? Can you pass a method which expect a TreeSet a LinkedHashSet?

No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.