Last Updated: 08 November, 2023
The HashSet class is a member of the Java Collection Framework. HashSet was introduced in the JDK 1.2 version and is available in the java.util package.
A HashSet is used to create an unordered collection of elements that contains only unique elements; no duplicate elements are allowed. The HashSet provides constant-time performance for general operations such as add, remove, contain, size, etc.
HashSet's internal implementation is based on the hash table for creating and storing a collection of unique elements.
Hash table: Actually, hash table is an instance of the HashMap class that uses a hashing mechanism for storing the information within a HashSet.
Hashing and HashCode: Hashing is the technique of mapping keys and values into the hash table by using a hash function. It is done for faster access to elements. The efficiency of mapping depends on the efficiency of the hash function used.
The hash code is an integer value associated with each object. It is used to identify the location of objects in the hash table. The hashCode() method is used to return the hash code value of the object in Java.
As we can see from the complete hierarchy above, HashSet extends the AbstractSet class and implements the Set interface as well as the Serializable and Cloneable interfaces.
Here, E defines the type of elements that the Set will contain.
Output
HashSet elements: [800, null, 500, 200]
The Java HashSet class has four constructors, as given below.
Constructor Name & Descriptions |
---|
public HashSet() This construct is used to create a new and empty HashSet object with a default initial capacity is 16 and a load factor is 0.75 HashSet<E> hs = new HashSet<E>(); |
public HashSet(int initialCapacity) This constructor is used to create a new and empty HashSet object in which the initial capacity is specified in the construct parameter and default load factor (0.75) HashSet<E> hs = new HashSet<E>(int initialCapacity); It will throw IllegalArgumentException if the initial capacity is less than zero. |
public HashSet(int initialCapacity, float loadFactor) This constructor is used to create a new and empty HashSet object in which the initialCapacity and loadFactor are specified in the construct parameters. HashSet<E> hs = new HashSet<E>(int initialCapacity, float loadFactor); Note: It will throw IllegalArgumentException if the initial capacity value is less than zero, or if the load factor is nonpositive value. |
public HashSet(Collection<? extends E> c) This constructor is used to create a HashSet object which contains the elements in the specified collection with a default load factor (0.75) and an initial capacity sufficient to contain the elements in the specified collection. HashSet<E> hs = new HashSet<E>(Collection C); Note: It will throw NullPointerException if the specified collection is null. |
Java HashSet class has the following methods.
Method | Description |
---|---|
public boolean add(E e) | Adds element to the set if it is not already present. Returns true if the set did not already contain the specified element otherwise return false. |
public boolean remove(Object o) | Removes the specified element from this set if it is present. Returns true if the set contained the specified element otherwise return false. |
public void clear() | Removes all of the elements from this set. The set will be empty after this call returns. |
public Object clone() | Returns a shallow copy of this HashSet instance: the elements themselves are not cloned. |
public boolean contains(Object o) | Returns true if this set contains the specified element otherwise return false. |
public boolean isEmpty() | Returns true if this set contains no elements otherwise return false. |
public int size() | Returns the number of elements in this set (its cardinality). |
public Iterator<E> iterator() | Returns an iterator over the elements in this set. The elements are returned in no particular order. |
public Spliterator<E> spliterator() | Creates a late-binding and fail-fast Spliterator over the elements in this set. |
The Java HashSet class provided methods are implemented in the below given examples. Let's go through the examples one by one and understand the uses for each method.
Before inserting the elements into the HashSet please note that insertion order is not preserved and also that duplicate elements are not allowed, but one null can be inserted.
Output
HashSet elements
[800, null, 500, 200]
HashSet elements after adding another HashSet
[800, null, 500, 20, 200, 40, 10, 30]
Output
HashSet elements: [50, 20, 70, 40, 10, 60, 30]
After calling remove() method: [50, 20, 70, 10, 60, 30]
After calling removeAll() method: [50, 10, 30]
After calling removeIf() method: [50, 30]
After calling retainingAll() method: []
HashSet before calling clear() method: [20, 70, 60]
After calling clear() method: []
Output
HashSet elements: [50, 20, 40, 10, 30]
50
20
40
10
30
50
20
40
10
30
Output
HashSet elements: [80, 50, 20, 70, 40, 10, 30]
HashSet Size: 7
Is HashSet Empty: false
HashSet contains() method: true
HashSet containsAll() method: false
ArrayList elements: [80, 50, 20, 70, 40, 10, 30]
Reference: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/HashSet.html
That's all guys, hope this Java article is helpful for you.
Happy Learning... 😀
feedback@javabytechie.com
What Java HashSet default Initial Capacity and Load Factor?
Initial Capacity: The initial capacity represents the size of the HashSet object to build. The capacity will be automatically increased if the current size gets full. HashSet's default initial capacity is 16.
Load Factor: The load factor is a measure of how full the HashSet is allowed to get before its capacity is automatically increased. When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is rehashed (that is, internal data structures are rebuilt) so that the hash table has approximately twice the number of buckets.
Load Factor = Number of stored elements in the table / Size of the hash table
When we create a new HashSet object its default capacity is 16 and the load factor is 0.75 then the object capacity will automatically get increased when the object size is equal to 12 (16 / 0.75) in it.
HashSet performance: HashSet has two major components Load factor and initial capacity which affect the performance of HashSet operations. The ideal and default load factor is 0.75. It provides very effective performance in terms of time and space complexity.
If we increase the load factor value more than that then memory overhead will be reduced (because it will decrease internal rebuilding operation) but, it will affect the add and search operation in the hashtable. To reduce the rehashing operation we should choose initial capacity wisely. If the initial capacity is greater than the maximum number of entries divided by the load factor, no rehash operation will ever occur.
How to synchronize HashSet in Java?
Ans. HashSet default implementation is not synchronized which means if multiple threads access a HashSet object at the same time and one of the threads modifies the hash set. Then it must be externally synchronized.
for making the HashSet object synchronized Java has provided a utility method that is Collections.synchronizedSet() method.
Set s = Collections.synchronizedSet(new HashSet(...));
The iterator returned by the HashSet class is fail-fast?
Ans. Yes, If the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the Iterator throws a ConcurrentModificationException.
Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
What is the difference between HashSet and HashMap in Java?
Ans. HashSet and HashMap have the following differences, as shown in the below table:
HashSet | HashMap |
---|---|
HashSet implements the Set interface. | HashMap implements the Map interface. |
HashSet is an unordered collection of elements that contains only unique elements. | HashMap stores elements in the form of key and value pairs and, keys must be unique. If the key is duplicated then the old key is replaced with the new value. |
HashSet implements Set, Cloneable, Serializable, Iterable and Collection interfaces. | HashMap implements Map, Cloneable, and Serializable interfaces. |
HashSet requires just one parameter for its object initialization. | HashMap requires two parameters (key and value) for its object initialization. |
HashSet can contain a single null value. | HashMap can contain a single null key and no restriction on any number of null values. |
For additing the element we use add() method. | Here, we use the put() method for adding an element. |
HashSet internally uses the HashMap object to store or add objects. | HashMap internally uses hashing to store or add objects. |
HashSet performance is slower than HashMap. | HashMap performance is faster than HashSet. |
In Java, what is the difference between HashSet and LinkedHashSet?
Ans. HashSet and LinkedHashSet are both implementations of the Set interface, and LinkedHashSet is a child class of the HashSet class. In the below-given table, we will see the differences between HashSet and LinkedHashSet:
HashSet | LinkedHashSet |
---|---|
The underlying data structure is a hash table. | The underlying data structure is a hash table + linked list (doubly linked list). |
Insertion order is not preserved. | Insertion order is preserved. |
HashSet requires less memory than the LinkedHashSet. | LinkedHashSet requires more memory than the HashSet. |
HashSet is a parent class of LinkedHashSet. | LinkedHashSet is a child class of HashSet. |
Introduced in JDK 1.2 Version. | Introduced in JDK 1.4 Version. |