HashSet in Java With Example

Here we will see about HashSet in java with Example.

Basic points about HashSet in Java.

  • HashSet is a class which implements Set, Cloneable, and Serializable interface but not RandomAccess interface.
  • HashSet used to store different types of elements.
  • HashSet stores the element in an unordered way.
  • In HashSet, none of the methods are Synchronized.
  • HashSet uses indexing representation to store the element.
  • HashSet doesn’t allow duplicate elements.
  • HashSet elements can be accessed randomly.
  • HashSet element can be accessed by using the Iterator but it can’t be accessed by using ListIterator.
  • We can have null in HashSet.

Example –

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

public class HashSetExample {
	public static void main(String[] args) {
		Set<String> setObject = new HashSet<>();

		setObject.add("ram");
		setObject.add("mohan");
		setObject.add("shyam");
		setObject.add("mohan");

		// duplicates are not allowed but it will not give
		// any compilation error
		setObject.add("ram");
		System.out.println("set object -- " + setObject);

	}
}

Output is – set object — [shyam, mohan, ram]

Different ways to iterate HashSet.

Using Iteartaor.

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

public class HashSetExample {
	public static void main(String[] args) {
		Set<String> setObject = new HashSet<>();

		setObject.add("ram");
		setObject.add("mohan");
		setObject.add("shyam");
		setObject.add("mohan");

		// duplicates are not allowed but it will not give
		// any compilation error
		setObject.add("ram");
		Iterator<String> it = setObject.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}

	}
}

Using for-each loop.

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

public class HashSetExample {
	public static void main(String[] args) {
		Set<String> setObject = new HashSet<>();

		setObject.add("ram");
		setObject.add("mohan");
		setObject.add("shyam");
		setObject.add("mohan");

		// duplicates are not allowed but it will not give
		// any compilation error
		setObject.add("ram");
		for (String str : setObject) {
			System.out.println(str);
		}

	}
}

Output is –

shyam
mohan
ram

Note – We can’t iterate HashSet using get() method, we don’t have get() method inside HashSet class like ArrayList. Also, we can’t iterate HashSet using ListIterator and Enumeration.

HashSet Constructors in Java with Example.

Constructors of HashSet.

  • HashSet()
  • HashSet(Collection c)
  • HashSet(int initialCapacity)
  • HashSet(int initialCapacity, float loadFactor, boolean dummyValue)

HashSet() – It creats a new and empty HashSet with default initial capacity 16 and load factor 0.75.  In fact in default constructor we have object of HashMap() something like below.


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

Example –

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

public class HashSetExample {
	public static void main(String[] args) {

		// Creating HashSet object using default constructor
		Set<String> setObject = new HashSet<>();

		setObject.add("ram");
		setObject.add("mohan");
		setObject.add("shyam");
		setObject.add("mohan");

		// duplicates are not allowed but it will not give
		// any compilation error
		setObject.add("ram");
		System.out.println(setObject);

	}
}

Output is – [shyam, mohan, ram]

HashSet(Collection c) – We can pass any type of collection classes which implements Collections interface and can convert it into HashSet. For example, we are going to convert ArrayList into HashSet in below example before that let’s see how this constructor has been defined in HashSet class.

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

Example –

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class HashSetConstructorExp {
	public static void main(String[] args) {
		List<String> listObject = new ArrayList<>();

		listObject.add("ram");
		listObject.add("mohan");
		listObject.add("shyam");
		listObject.add("mohan");
		listObject.add("ram");
		System.out.println("list of Arraylist -- " + listObject);

		// We can convert arraylist into hashset using HashSet argumented
		// constructor
		Set<String> setTypeObject = new HashSet(listObject);
		System.out.println("set types of object -- " + setTypeObject);

	}
}

Output is –

list of Arraylist — [ram, mohan, shyam, mohan, ram]
set types of object — [shyam, mohan, ram]

HashSet(int initialCapacity) – We can create a new HashSet defining some different capacity than 16 using this constructor.

Internal implementation –

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

Example –

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

public class HashSetConstructorExmp4 {
	public static void main(String[] args) {

		// Creating HashSet object passing initial capacity 25
		Set<String> setObject = new HashSet<>(25);

		setObject.add("ram");
		setObject.add("mohan");
		setObject.add("shyam");
		setObject.add("mohan");
		System.out.println(setObject);
	}
}

Output is – [mohan, shyam, ram]

HashSet(int initialCapacity, float loadFactor, boolean dummyValue) – We can also create a new HashSet with new capacity as well as new load factor, rather than 16 and 0.75.

Internal implementation –


  HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }
import java.util.HashSet;
import java.util.Set;

public class HashSetConstExamp {
	public static void main(String[] args) {

		// Creating HashSet object passing initial capacity 20
		// and default load factor 0.65
		Set<String> setObject = new HashSet<>(20, 0.65f);

		setObject.add("ram");
		setObject.add("mohan");
		setObject.add("shyam");
		setObject.add("mohan");
		System.out.println(setObject);

	}
}

Output is – [mohan, shyam, ram]

How HashSet works internally in java.

In this section, we will see how HashSet works internally in java.

  • HashSet internally uses HashMap to store the elements.
  • There is a HashMap reference has been defined inside HashSet class.
    private transient HashMap<E,Object> map;
  • Inside add() method it has been called HashMap’s put method.
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
  • Since put method store the elements in the key-value pair, there is a dummy Object has been defined.
private static final Object PRESENT = new Object();
  • Inside HashSet default constructor, HashMap has been instantiated.
    public HashSet() {
        map = new HashMap<>();
    }
  • We don’t have get() method inside Set as we have in List. So we can iterate HashSet using Iterator, for-each loop or Java 8 features.

HashSet internal implementation – 


public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{
    

    private transient HashMap<E,Object> map;


    private static final Object PRESENT = new Object();

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

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

Adding User-Defined Objects in HashSet with Example.

In this section, we will see what happens if we add a user-defined Object in HashSet. When we add wrapper class(Integer, String, Float, etc) in Set it will not allow duplicate elements. Suppose we have a class called EmployeeCon which has two attributes name and id. We are trying to add a couple of EmployeeCon objects with the same name and id something like below.

Set<EmployeeCon> empset=new HashSet<>();
EmployeeCon e1=new EmployeeCon(101,"sita");
EmployeeCon e2=new EmployeeCon(101,"sita");
EmployeeCon e3=new EmployeeCon(101,"sita");
EmployeeCon e4=new EmployeeCon(101,"sita");

What is the size of empset one or four, because we have same id and name?

If we add a user-defined class in Set, It will be treated as a different object until we don’t override equals() and hashcode() method and yes the size of empset will be four.

Let’s see a simple example where we will add EmployeeCon object –

package collectionint1;
import java.util.*;
class EmployeeCon{
	String name;
	int id;
	EmployeeCon(int i,String s){
		this.id=i;
		this.name=s;
	}

	
}
public class AllowDupEmpUsingCons {
	public static void main(String[] args) {
		Set<EmployeeCon> empset=new HashSet<>();
		EmployeeCon e1=new EmployeeCon(101,"sita");
		EmployeeCon e2=new EmployeeCon(101,"sita");
		EmployeeCon e3=new EmployeeCon(101,"sita");
		EmployeeCon e4=new EmployeeCon(101,"sita");
		
		empset.add(e1);
		empset.add(e2);
		empset.add(e3);
		empset.add(e4);
		
		for(EmployeeCon e:empset) {
			System.out.println(e.id+"  "+e.name);
		}
	}

}

Output is – 

We can see id 101 and name sita is coming four times in output. So question arises why Wrapper classes type of Set doesn’t allow duplicate where as if we have User defined class type class(EmployeeCon)  it allow duplicate elements. Here we are passing EmployeeCon object in Set which doesn’t have overridden equals() and hashCode() method.

Note – All wrapper class overrides equals() and hashCode().

StringBuffer doesn’t override equals() and hashCode(), so as per above discussion it should allow duplicate element  if we are going to add StringBuffer type in Set.

Let’s see example of StringBuffer type of set –

package collectionint1;

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

public class StringBufferAllowsDuplicateSetExample {
	public static void main(String[] args) {
		Set<StringBuffer> stringBufferSet=new HashSet<>();
	
		stringBufferSet.add(new StringBuffer("ram"));
		stringBufferSet.add(new StringBuffer("ram"));
		stringBufferSet.add(new StringBuffer("ram"));
		stringBufferSet.add(new StringBuffer("ram"));
		stringBufferSet.add(new StringBuffer("ram"));
		System.out.println(stringBufferSet);
	}
}

Output of above program is – 

We can see we have duplicate element even in Set if we try to add StringBuffer type of elements.

So what will happen if we override equals() and hashCode() in our EmplyeeCons class, will it allow duplicate elements. No,  it will not allow duplicate elements.

Let’s see example where we are going to override equals() and hashCode() and give default eclipse logic inside equals() and hashCode() –

package collectionint1;

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

class Employee3{
	String name;
	int id;
	Employee3(int i,String s){
		this.id=i;
		this.name=s;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee3 other = (Employee3) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	

}

public class AvoidDuplicateElementUserDefineClass {
	public static void main(String[] args) {
		Set<Employee3> empset=new HashSet<>();
		Employee3 e1=new Employee3(101,"sita");
		Employee3 e2=new Employee3(101,"sita");
		Employee3 e3=new Employee3(101,"sita");
		Employee3 e4=new Employee3(101,"sita");
		
		empset.add(e1);
		empset.add(e2);
		empset.add(e3);
		empset.add(e4);
		
		for(Employee3 e:empset) {
			System.out.println(e.id+"  "+e.name);
		}
	}
}

Output of above program is –

HashSet Method in Java with Example.

That’s all about HashSet in Java With Example.

Some more article related to HashSet in Java.

How to create custom HashSet in Java.

HashSet Docs.

Summary – We have seen HashSet in Java With Example. We covered Constructors and methods of HashSet with example.