This tutorial explain what is HashSet in Java, HashSet methods, how to implement and iterate through it and other related concepts with the help of programming examples:
A HashSet is a collection that stores objects. The HashSet in Java is implemented using the ‘HashSet’ class of java.util package.
This class implements a set interface. It uses HashTable which is a HashMap instance for storage.
=> Take A Look At The Java Beginners Guide Here.
Table of Contents:
Java HashSet
Some of the characteristics of HashSet are given below:
- Implements a Set interface that has HashTable as an internal structure. HashTable, in turn, is a HashMap instance.
- It does not preserve the order of elements. Elements are stored in random order.
- HashSet does not allow duplicate values.
- Implements a Cloneable and Serializable interface apart from the Set interface.
- We can have null values in HashSet.
HashSet Class Hierarchy
The hierarchy of the HashSet class is given below:
As shown in the above figure, HashSet class extends AbstractSet class that in turn implements the Set interface. The set interface inherits the Collection interface that in turn extends the Iterable interface.
Java 8 release introduced a new method ‘spliterator’ in HashSet which creates a fail-fast spliterator that performs late-binding over the elements of the HashSet.
The general declaration of the HashSet class is:
public class HashSet<E> extends AbstractSet<E> implements Set<E>,
Cloneable, Serializable
Import HashSet
We can include the HashSet functionality into the program using the import statement as shown below:
import java.util.HashSet;
or
import java.util.*;
Declare HashSet In Java
We can create a HashSet object in Java as given below:
HashSet h = new HashSet();
HashSet class provides the following constructors to create objects.
Constructor prototype | Description |
---|---|
HashSet() | Default constructor for HashSet |
HashSet(int capacity) | Constructs a HashSet object with the given ‘capacity’. |
HashSet(int capacity, float loadFactor) | Constructs a HashSet object with the given ‘capacity’ and ‘loadFactor’. |
HashSet(Collection < ? extends E >c) | Construct a HashSet object from given collection. |
As shown in the above table, apart from the default constructor, this class also provides the constructors that take capacity and loadfactor and another collection as its arguments. We can create the objects of this class using any of these constructors.
Initialize HashSet
The following Java code shows the declaration and initialization of the HashSet class object. In this program, we create a HashSet class object from an ArrayList. Initially, we create and initialize ArrayList and then use this ArrayList to create and initialize a HashSet object.
import java.util.*; class Main{ public static void main(String args[]){ //declare and initialize ArrayList ArrayList&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; myList=new ArrayList&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); myList.add("Red"); myList.add("Green"); myList.add("Blue"); //Create a HashSet and provide ArrayList in its constructor HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; mySet=new HashSet(myList); mySet.add("Yellow"); //print the HashSet System.out.println("The HashSet contents:"); Iterator&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; i=mySet.iterator(); while(i.hasNext()) { System.out.print(i.next() + "\t"); } } }
Output:
How Do HashSet Work Internally In Java?
Internally, it is implemented using a HashTable. HashTable is an instance of HashMap. But HashMap is a collection of key-value pairs. So how do we store HashSet in a HashMap?
The object values of HashSet are the keys to the HashMap.
Java HashSet Example
Let’s see a detailed example of HashSet in Java.
import java.util.*; class Main{ public static void main(String args[]){ //Create a HashSet and add elements to it HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; mySet=new HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); mySet.add("Blue"); mySet.add("Green"); mySet.add("Blue"); mySet.add("Green"); mySet.add("Red"); mySet.add("Brown"); mySet.add("Yellow"); //Iterate through the HashSet and print its elements System.out.println("HashSet contents:"); Iterator&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; itr=mySet.iterator(); while(itr.hasNext()){ System.out.print(itr.next() + "\t"); } } }
Output:
Here, we use the default constructor to create a HashSet object. Then using the add method we add elements (colors) to the HashSet. Next, we use an iterator to traverse through the HashSet and print the contents.
HashSet Iterator
In Java, HashSet can be traverse or iterated in two ways as discussed below.
Without Using Iterator
Here, we do not define an iterator on the HashSet. Instead, we use a forEach loop. The following program shows the traversal of HashSet using a forEach loop.
import java.util.HashSet; import java.util.Set; class Main{ public static void main(String[] args) { // Create a HashSet Set&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; cities_HashSet = new HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); //Initialize HashSet with elements cities_HashSet.add("Mumbai"); cities_HashSet.add("Delhi"); cities_HashSet.add("Pune"); cities_HashSet.add("Chennai"); cities_HashSet.add("Bangaluru"); //use foreach loop to iterate through the HashSet System.out.println("HashSet contents:"); for (String city : cities_HashSet) { System.out.print(city + " "); } } }
Output:
Using Iterator
The next approach of iterating is using an iterator. Here, we define an iterator for the HashSet class and then traverse through it.
The following program shows this approach.
import java.util.HashSet; import java.util.Set; import java.util.Iterator; class Main{ public static void main(String[] args) { // Create a HashSet Set&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; cities_HashSet = new HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); //Initialize HashSet with elements cities_HashSet.add("Mumbai"); cities_HashSet.add("Delhi"); cities_HashSet.add("Pune"); cities_HashSet.add("Chennai"); cities_HashSet.add("Bangaluru"); //use iterator to iterate through the HashSet System.out.println("HashSet contents using Iterator:"); Iterator&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; iter = cities_HashSet.iterator(); while(iter.hasNext()){ System.out.print(iter.next() + " "); } } }
Output:
HashSet Methods/API
The following table shows the methods provided by the HashSet class. We have provided the prototype and description for each method. As seen, we have methods for basic operations like add, remove, size, etc. as well as for other methods to check for contents, emptiness, iterator, spliterator, etc.
Method | Method Prototype | Description |
---|---|---|
add | Boolean add(E e) | Adds given element e to the HashSet if not already present. |
clear | Void clear() | Clears or removes all elements from the HashSet |
clone | Object clone() | It is used to return a shallow copy of this HashSet instance: the elements themselves are not cloned. |
contains | Boolean contains(Object o) | Checks if the HashSet contains the given object o and returns true if yes. |
isEmpty | Boolean isEmpty() | Checks if the HashSet is empty. Returns true if yes. |
iterator | Iterator< E> iterator() | Returns an iterator that is used to traverse the HashSet. |
remove | Boolean remove(Object o) | Removes the given element o from the HashSet if it is part of the HashSet. |
size | Int size() | Returns the size or number of elements present in the HashSet. |
spliterator | Spliterator< E> spliterator() | Returns fail-fast and late-binding spliterator to traverse the HashSet. This method was introduced in Java 8. |
We have described the methods provided by the HashSet class, now let’s implement an example that demonstrates the major methods of the class.
The below Java program demonstrates the methods of this class.
import java.util.*; class Main{ public static void main(String args[]){ //create a HashSet and initialize it HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; colors_set=new HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); colors_set.add("Red"); colors_set.add("Green"); colors_set.add("Blue"); colors_set.add("Cyan"); System.out.println("Initial HashSet: "+colors_set); //remove() method =&amp;amp;amp;amp;amp;amp;amp;gt; remove specified element colors_set.remove("Red"); System.out.println("\nHashSet after remove(Red): "+colors_set); //declare and initialize another list HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; colors_hash=new HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); colors_hash.add("Yellow"); colors_hash.add("Magenta"); //addAll() method =&amp;amp;amp;amp;amp;amp;amp;gt; add another HashSet to existing colors_set.addAll(colors_hash); System.out.println("\nHashSet after add(colors_hash): "+colors_set); //removeAll() method =&amp;amp;amp;amp;amp;amp;amp;gt; remove all elements specified in the argument colors_set.removeAll(colors_hash); System.out.println("\nHashSet after removeAll(colors_hash) method: "+colors_set); //removeIf() =&amp;amp;amp;amp;amp;amp;amp;gt; remove if given condition is fulfilled colors_set.removeIf(str-&amp;amp;amp;amp;amp;amp;amp;gt;str.contains("Green")); System.out.println("\nHashSet after removeIf(contains(Green)) method: "+colors_set); //clear() =&amp;amp;amp;amp;amp;amp;amp;gt; delete all elements from the HashSet colors_set.clear(); System.out.println("\nHashSet after clear() method: "+colors_set); } }
Output:
Convert HashSet To Array
We can use the toArray () method of HashSet to convert the given HashSet to an array. Note that the data type and size of the Array should match that of HashSet.
The following Java program shows this conversion.
import java.util.HashSet; class Main{ public static void main(String[] args) { // Create a HashSet &amp;amp;amp;amp;amp;amp;amp;amp; inintialize it HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; num_HashSet = new HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); num_HashSet.add("One"); num_HashSet.add("Two"); num_HashSet.add("Three"); num_HashSet.add("Four"); // Print HashSet contents System.out.println("HashSet contents: "+ num_HashSet); // Declare an array with size = HashSet size String[] numArray = new String[num_HashSet.size()]; //use toArray method to convert HashSet to an array num_HashSet.toArray(numArray); // Print Array System.out.println("Array from HashSet: "); for(String val : numArray){ System.out.print(val + " "); } } }
Output:
Sort A HashSet
We can sort a HashSet in Java. HashSet elements are not sorted originally as it does not maintain the order of elements. We can follow two approaches to sort a HashSet in Java.
Using Collections.sort () Method
In this approach, we convert the HashSet into a list. Then, we use the Collections.sort () method to sort the list. This list is then printed.
import java.util.*; public class Main { public static void main(String args[]) { // Create a HashSet &amp;amp;amp;amp;amp;amp;amp;amp; initialize it HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; cities_HashSet = new HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); cities_HashSet.add("Pune"); cities_HashSet.add("Mumbai"); cities_HashSet.add("Bangaluru"); cities_HashSet.add("Hyderabad"); System.out.println("Original HashSet: " + cities_HashSet); // Convert HashSet to ArrayList List&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; cities_list = new ArrayList&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(cities_HashSet); // Use Collections.sort () method to sort the list Collections.sort(cities_list); // Print the Sorted ArrayList (HashSet) System.out.println("Sorted HashSet:"+ cities_list); } }
Output:
By Converting HashSet To TreeSet
Using this approach we convert the HashSet to TreeSet. TreeSet maintains the order of the elements. Hence when the HashSet is coverted to TreeSet, the elements are put in order.
The following Java program shows this conversion thereby sorting the HashSet.
import java.util.*; public class Main { public static void main(String args[]) { // Create and initialize a HashSet HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; cities_HashSet = new HashSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(); cities_HashSet.add("Pune"); cities_HashSet.add("Mumbai"); cities_HashSet.add("Bangaluru"); cities_HashSet.add("Hyderabad"); System.out.println("Original HashSet:"+ cities_HashSet); // Sort HashSet using TreeSet TreeSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt; treeSet = new TreeSet&amp;amp;amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;amp;amp;gt;(cities_HashSet); // Print the sorted HashSet System.out.println("HashSet sorted using using TreeSet:" + treeSet); } }
Output:
Let’s now discuss some of the differences between HashSet and HashMap. We will also discuss the differences between HashSet and TreeSet.
HashSet Vs HashMap
The following table shows the major differences between HashSet and HashMap.
HashSet | HashMap |
---|---|
Implements Set interface. | Implements Map interface. |
Stores objects of a particular type. | Store key-value pairs of data. |
Does not allow duplicate values of objects. | Allows duplicate values but not duplicate keys. |
Can have a single null value. | Allows single null key and multiple null values. |
Internally uses HashMap Object for storing data . | Uses hashing technique for storing data. |
Is slower when compared to HashMap. | HashMap is faster. |
Objects are added using the Add () method. | HashMap uses the put () method to add key-value pairs. |
HashSet Vs TreeSet
Enlisted below are the differences between HashSet and TreeSet.
HashSet | TreeSet |
---|---|
It does not maintain element ordering. Stores objects in random order. | Maintains the natural ordering of the elements. |
It allows for null values. | It cannot have null values. |
Gives better performance as it takes constant time for basic operations. | Offers log n time cost for basic operations. |
Much faster than Treeset. | Treeset is slower. |
Internally implemented using HashMap. | Treeset is internally implemented using navigable Treemap. |
Uses equals () method for comparison. | Uses compareTo () method for comparison. |
Has limited functionality. | Provides may functions that offer various operations and makes it easier to use Treeset than HashSet. |
Frequently Asked Questions
Q #1) How does HashSet work in Java?
Answer: HashSet in Java uses HashMap to store the object. One HashMap object is created when a HashSet object is created. The elements or objects entered in the HashSet are stored as keys in the HashMap.
Q #2) Is HashSet ordered in Java?
Answer: No, it is not ordered in Java. It stores elements in random order.
Q #3) Does HashSet allow null?
Answer: yes, it allows a single null value. This means that only a single element or object can be null and not all.
Q #4) Why is HashSet used in Java?
Answer: It is used to store key-value pairs in Java. It is similar to HashTable with the exception that HashSet is unsynchronized and unlike HashTable it allows null values and a single null key. HashSet is not ordered and can be used to store unordered objects or when the order of the objects is not required.
Q #5) Is HashSet synchronized in Java?
Answer: The HashSet is not synchronized in Java. Also, it is not thread-safe. But we can make it synchronized using the synchronizedSet () method.
Conclusion
HashSet is a collection containing objects that are in random order. HashSet class that implements HashSet in Java internally uses HashTable that implements HashMap.
We saw the declaration and initialization of HashSet along with the methods provided by the HashSet class.
=> Read Through The Easy Java Training Series.