HashSet in java

The HashSet in java is most important part of the Java Collection Framework. The HashSet class implements the Set interface and extends the AbstractSet class. It also implements the Cloneable and Serializable interface.

You can read it with an example from here.
1. What is HashSet in Java?
2. Important points HashSet in java?
3. Creation of HashSet in java?

4. HashSet Implementation in java?
5. HashSet internal implementation in java?
6. Internal working of HashSet in java?
7. Why duplicate not allowed in HashSet?
8. Why HashSet can contain only one null?
6. How to add elements in HashSet?
7. How to remove elements from HashSet?

8. Immutable Set in Java?

hashset in java

1. What is HashSet in Java?

As we can see HashSet implements the Set interface so it can contain only the unique objects. HashSet class uses the hash table for storage by use of hashing technique. We will discuss it in a separate post on how the HashSet internal implementation in java?. There are a lot of things about HashSet that make it an important part of the collection framework. Let’s discuss important points about HashSet.

2. Important points HashSet in java

1.  HashSet can’t contain duplicate objects because it implements Set interface that enforces the rule, the object must be unique.
2. A HashSet doesn’t maintain any order of elements. The order of objects does not depend on the insertion because each object inserted based on hashCode. You can’t find the position of element in HashSet.
3. HashSet can contain only one null value.
4. HashSet is not synchronized.
5. HashSet internally uses HashMap and HashTable. We will discuss it in detail.
6. The initial default capacity of HashSet is 16, and the load factor is 0.75.
7. The iterator return by HashSet class is fail-fast. It means we can’t modify HashSet after the creation of iterator. If we try to modify it, It will throw ConcurrentModificationException.
8. HashSet increases the capacity itself when we insert elements like ArrayList.

3. Creation of HashSet in java

We can create a HashSet by use of any constructor of the HashSet class. The HashSet class provides four constructors, but each has a different purpose. Let’s discuss all the constructors of the HashSet class.

There are four constructors that are used to create a HashSet. We will cover all the four constructors and also see the difference.

1. HashSet()

It is a default constructor of the HashSet class. It is used to create an empty HashSet with initial default capacity 16. This constructor doesn’t take any parameter.

 import java.util.HashSet;
import java.util.Set;

public class HashSetExample
{
    public static void main(String[] args) 
    {
    	Set<Integer> integerHashSet = new HashSet<Integer>();
    	integerHashSet.add(1);
    	integerHashSet.add(2);
    	integerHashSet.add(3);
    	integerHashSet.add(4);
    	integerHashSet.add(5);
    	
    	System.out.println("HashSet of Integer: "+ integerHashSet);
    	
    	Set<String> stringHashSet = new HashSet<String>();
    	stringHashSet.add("Hi");
    	stringHashSet.add("Java");
    	stringHashSet.add("Goal");
    	stringHashSet.add("Learning");
    	stringHashSet.add("Website");
    	
    	System.out.println("HashSet of String: "+ stringHashSet);
    }
}

Output: HashSet of Integer: [1, 2, 3, 4, 5]
HashSet of String: [Learning, Hi, Java, Goal, Website]

2. HashSet(int capacity)

This is a parameterized constructor of the HashSet class. It takes one parameter of int type that is the capacity of HashSet. We can initialize the capacity of HashSet by the use of this constructor. It throws IllegalArgumentException, if given argument value is less than 0.

import java.util.HashSet;
import java.util.Set;

public class HashSetExample
{
    public static void main(String[] args) 
    {
    	Set<Integer> integerHashSet = new HashSet<Integer>(8);
    	integerHashSet.add(1);
    	integerHashSet.add(2);
    	integerHashSet.add(3);
    	integerHashSet.add(4);
    	integerHashSet.add(5);
    	
    	System.out.println("HashSet of Integer: "+ integerHashSet);
    	
    	Set<String> stringHashSet = new HashSet<String>(9);
    	stringHashSet.add("Hi");
    	stringHashSet.add("Java");
    	stringHashSet.add("Goal");
    	stringHashSet.add("Learning");
    	stringHashSet.add("Website");
    	
    	System.out.println("HashSet of String: "+ stringHashSet);
    }
}

Output: HashSet of Integer: [1, 2, 3, 4, 5]
HashSet of String: [Learning, Hi, Java, Goal, Website]

3. HashSet(int capacity, float loadFactor)

This method is used to set the capacity and load factor of HashSet. It takes two parameters, one is int type and another is float. It throws IllegalArgumentException if the given capacity is less
than zero, or load factor is nonpositive.

import java.util.HashSet;
import java.util.Set;

public class HashSetExample
{
    public static void main(String[] args) 
    {
    	Set<Integer> integerHashSet = new HashSet<Integer>(8, 0.6f);
    	integerHashSet.add(1);
    	integerHashSet.add(2);
    	integerHashSet.add(3);
    	integerHashSet.add(4);
    	integerHashSet.add(5);
    	
    	System.out.println("HashSet of Integer: "+ integerHashSet);
    	
    	Set<String> stringHashSet = new HashSet<String>(9, 0.6f);
    	stringHashSet.add("Hi");
    	stringHashSet.add("Java");
    	stringHashSet.add("Goal");
    	stringHashSet.add("Learning");
    	stringHashSet.add("Website");
    	
    	System.out.println("HashSet of String: "+ stringHashSet);
    }
}

Output: HashSet of Integer: [1, 2, 3, 4, 5]
HashSet of String: [Learning, Hi, Java, Goal, Website]

4. HashSet(Collection c)

This constructor takes one parameter of Collection type. It creates an object of HashSet that contains all element from specified collection c. Its load factor is 0.75 and capacity depends upon elements presents in Collection.

import java.util.HashSet;
import java.util.Set;

public class HashSetExample
{
    public static void main(String[] args) 
    {
    	Set<Integer> integerHashSet = new HashSet<Integer>();
    	integerHashSet.add(1);
    	integerHashSet.add(2);
    	integerHashSet.add(3);
    	integerHashSet.add(4);
    	integerHashSet.add(5);
    	
    	Set<Integer> integerHashSet2 = new HashSet<Integer>(integerHashSet);
    	
    	System.out.println("HashSet of Integer: "+ integerHashSet2);
    	
    	Set<String> stringHashSet = new HashSet<String>();
    	stringHashSet.add("Hi");
    	stringHashSet.add("Java");
    	stringHashSet.add("Goal");
    	stringHashSet.add("Learning");
    	stringHashSet.add("Website");
    	
    	Set<String> stringHashSet2 = new HashSet<String>(stringHashSet);
    	
    	System.out.println("HashSet of String: "+ stringHashSet2);
    }
}

Output: HashSet of Integer: [1, 2, 3, 4, 5]
HashSet of String: [Learning, Hi, Java, Goal, Website]

4. HashSet implementation in java

HashSet internally uses HashMap to perform the operation on HashSet. We will cover this in a separate topic and see how HashSet uses the HashMap. Here we will see how HashSet contains the element and how we can traverse the elements.

import java.util.HashSet;
import java.util.Set;

class Student
{
	int rollNo;
	String name;
	String className;
	
	public int getRollNo() {
		return rollNo;
	}
	public void setRollNo(int rollNo) {
		this.rollNo = rollNo;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public Student(int rollNo, String name, String className) {
		this.rollNo = rollNo;
		this.name = name;
		this.className = className;
	}
	
	
}

public class HashSetExample
{
    public static void main(String[] args) 
    {
    	Set<Student> studentData = new HashSet<Student>();
    	studentData.add(new Student(1, "A", "MCA"));
    	studentData.add(new Student(2, "B", "BCA"));
    	studentData.add(new Student(8, "C", "MCA"));
    	studentData.add(new Student(10, "D", "BSC"));
    	
    	for(Student student : studentData)
    		System.out.println("RollNo: "+student.getRollNo() + ", Name: "+ student.getName());
    	
    }
}

Output: RollNo: 1, Name: A
RollNo: 10, Name: D
RollNo: 8, Name: C
RollNo: 2, Name: B

5. HashSet internal implementation in java

In this section we will see, how the internal working of HashSet in java or How HashSet stores only unique values. It most common and important question of core java. A HashSet contains only unique values and can contain only one null value. So, let’s find the answer and also discuss the HashSet internal implementation in java.

6. Internal working of HashSet in java?

The HashSet internally uses HashMap to store the objects. Before a deep dive, we recommend you should be familiar with HashMap. Whenever we create an object HashSet, internally creates the object of HashMap also. Let’s see the code of each constructor of HashSet in JDK

public HashSet() 
{
    map = new HashMap<>();
}

public HashSet(int initialCapacity) 
{
    map = new HashMap<>(initialCapacity);
}
	
public HashSet(int initialCapacity, float loadFactor)
{
     map = new HashMap<>(initialCapacity, loadFactor);
}
	
public HashSet(Collection<? extends E> c) 
{
       map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
       addAll(c);
}

As we can see the constructor of HashSet creates the object of HashMap. The object of HashMap stores all the elements that we enter in the HashSet. Now the question arises HashMap always stores the data based on key and value pair. But in the HashSet, we just provide the value. Let’s have a look at the add(E e) method of HashSet.

public boolean add(E e) 
{
        return map.put(e, PRESENT)==null;
 }

The element that we add into HashSet stores as keys of this HashMap object and a constant store as value.

7. Why duplicates are not allowed in HashSet?

Everyone knows a HashSet doesn’t contain duplicate values. We can add values in HashSet by use of add(E e) method, it returns true if the element is not already present in HashSet otherwise false. The add(E e) method uses the object of HashMap and put the element as a key and a constant called “PRESENT” as a value. This “PRESENT” is defined in the HashSet class as below.

// Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();
	
public boolean add(E e)
{
    return map.put(e, PRESENT)==null;
}

The “PRESENT” is a static final object of the Object class that is used to put a value in HashMap. We already know a HashMap can’t contain duplicate keys.
Let’s take java hashset example, how it works internally in memory and HashSet implementation in java.

import java.util.HashSet;
import java.util.Set;

public class HashSetExample
{
    public static void main(String[] args) 
    {
    	Set<String> hashSet = new HashSet<String>();
    	hashSet.add("Hello");
    }
}

The add(E e) method invokes the put(e, PRESNT) method, it returns null if element e is not existing in HashMap. If element e exists, then it returns the element.

Hashset internal implementation in java

Let’s try to add a duplicate element in HashSet.

import java.util.HashSet;
import java.util.Set;

public class HashSetExample
{
    public static void main(String[] args) 
    {
    	Set<String> hashSet = new HashSet<String>();
    	hashSet.add("Hello");
    	hashSet.add("Hello");
    	System.out.println("Size of HashSet: "+hashSet.size());
    }
}

It is not adding the duplicate value because a HashMap can’t contain the duplicate key. So the put(e, PRESENT) method returns an object that is not equal to null.

import java.util.HashSet;
import java.util.Set;

public class HashSetExample
{
    public static void main(String[] args) 
    {
    	Set<String> hashSet = new HashSet<String>();
    	hashSet.add("Hello");
    	hashSet.add("Java");
    	hashSet.add("Goal");
    	System.out.println("Size of HashSet: "+hashSet.size());
    }
}
hashset internal implementation in java

8. Why HashSet can contain only one null?

As we have discussed HashSet internally uses the HashMap. So, when we add the element in HashSet, it internally adds the element in the object of HashMap as we have discussed in the above section.

So, when we add the null value more than one time, it is considered a duplicate in HashSet because internal HashMap can contain only a unique key.  

Leave a Comment