HashSet in Java

Learn HashSet in Java with practical examples, explanations, best practices, and real-world coding techniques.

HashSet in Java is a collection used to store unique elements. It is part of the Java Collections Framework and is backed by a hash table implementation.

Unlike an ArrayList, a HashSet does not allow duplicate elements. It is particularly useful when the main requirement is to determine whether a value exists, remove duplicates, or maintain a collection of unique values without requiring sorted order.

What Is HashSet in Java?

HashSet<E> implements the Set interface. A Set represents a collection in which duplicate elements are not allowed.

For example, if the same language is added multiple times, HashSet keeps only one occurrence.

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

Set<String> languages = new HashSet<>();

languages.add("Java");
languages.add("Python");
languages.add("Java");

System.out.println(languages);

The second "Java" does not create another element because HashSet only stores unique values.

Creating a HashSet

A HashSet is commonly declared using the Set interface and initialized with the HashSet implementation.

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

Set<Integer> numbers = new HashSet<>();

numbers.add(10);
numbers.add(20);
numbers.add(30);

Using the Set interface makes it possible to change the implementation later if the application's ordering or performance requirements change.

Adding Elements to HashSet

Use the add() method to insert an element. The method returns true when the set changes and false when the element was already present.

Set<String> skills = new HashSet<>();

boolean first = skills.add("Java");
boolean second = skills.add("Python");
boolean duplicate = skills.add("Java");

System.out.println(first);
System.out.println(second);
System.out.println(duplicate);

System.out.println(skills);

The third call returns false because "Java" is already contained in the set.

Checking Whether an Element Exists

Use contains() to check whether an element is present. This is one of the main reasons HashSet is useful compared with a list when frequent membership checks are required.

Set<String> technologies = new HashSet<>();

technologies.add("Java");
technologies.add("Python");
technologies.add("C#");

System.out.println(technologies.contains("Java"));
System.out.println(technologies.contains("Go"));

Removing Elements from HashSet

The remove() method removes a specified element. It returns true if the set contained the element.

Set<String> languages = new HashSet<>();

languages.add("Java");
languages.add("Python");
languages.add("C#");

languages.remove("Python");

System.out.println(languages);

Unlike an ArrayList, HashSet does not use indexes, so elements are removed by their values rather than by a numeric position.

Iterating Through a HashSet

HashSet can be traversed using an enhanced for loop.

Set<String> languages = new HashSet<>();

languages.add("Java");
languages.add("Python");
languages.add("C#");

for (String language : languages) {
    System.out.println(language);
}

HashSet does not guarantee a predictable iteration order. The order in which elements are printed should not be treated as insertion order or sorted order.

HashSet and Duplicate Values

The defining property of HashSet is that duplicate elements are ignored. This makes it useful for quickly removing duplicate values from a collection.

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

List<Integer> numbers = new ArrayList<>();

numbers.add(10);
numbers.add(20);
numbers.add(10);
numbers.add(30);
numbers.add(20);

Set<Integer> uniqueNumbers = new HashSet<>(numbers);

System.out.println(uniqueNumbers);

The resulting set contains each distinct value only once.

HashSet with Null Values

HashSet permits a single null element. Adding null again does not create another null entry.

Set<String> values = new HashSet<>();

values.add("Java");
values.add(null);
values.add(null);

System.out.println(values);
System.out.println(values.contains(null));

HashSet Size and Empty Check

Use size() to find the number of unique elements and isEmpty() to determine whether the set contains no elements.

Set<Integer> numbers = new HashSet<>();

numbers.add(10);
numbers.add(20);
numbers.add(10);

System.out.println(numbers.size());
System.out.println(numbers.isEmpty());

The size is 2 because the value 10 occurs only once in the set.

Clearing a HashSet

The clear() method removes every element from the set.

Set<String> languages = new HashSet<>();

languages.add("Java");
languages.add("Python");

languages.clear();

System.out.println(languages);
System.out.println(languages.isEmpty());

Set Operations in Java

HashSet can perform common mathematical set operations through methods provided by the Set interface.

Union

addAll() can be used to combine the unique elements from two sets.

Set<Integer> first = new HashSet<>();
first.add(1);
first.add(2);
first.add(3);

Set<Integer> second = new HashSet<>();
second.add(3);
second.add(4);
second.add(5);

Set<Integer> union = new HashSet<>(first);
union.addAll(second);

System.out.println(union);

Intersection

retainAll() keeps only elements that are present in both sets.

Set<Integer> common = new HashSet<>(first);
common.retainAll(second);

System.out.println(common);

Difference

removeAll() removes elements that are also present in another collection.

Set<Integer> difference = new HashSet<>(first);
difference.removeAll(second);

System.out.println(difference);

HashSet vs ArrayList

HashSet and ArrayList are both commonly used collections, but they are designed for different access patterns.

Feature HashSet ArrayList
Duplicates Not allowed Allowed
Index access Not supported Supported
contains() O(1) average O(n)
Ordering No guaranteed order Insertion order
Primary use Uniqueness and membership Ordered indexed data

HashSet vs HashMap

HashSet and HashMap both use hashing internally, but their purposes are different.

Feature HashSet HashMap
Stores Values Key-value pairs
Duplicate values Not allowed Allowed
Key Not applicable Unique
Primary use Unique values Key-based lookup

HashSet Time Complexity

HashSet is designed to provide efficient average-case operations through hashing.

Operation Average Complexity
add() O(1)
contains() O(1)
remove() O(1)
size() O(1)
Iteration O(n)

These are typical average-case complexities. Actual behavior can be affected by hashing, collisions, resizing, and the implementation of the elements stored in the set.

HashSet and hashCode()

HashSet relies on hashCode() and equals() to determine whether elements are equivalent. This becomes especially important when custom objects are stored in a HashSet.

If two objects are considered equal according to equals(), they must return the same hash code. Correctly implementing both methods is therefore important when custom objects represent set elements.

HashSet with Custom Objects

HashSet can store custom objects, but duplicate detection depends on the object's equality and hash-code contract.

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

class User {
    int id;
    String name;

    User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof User)) {
            return false;
        }

        User other = (User) obj;

        return id == other.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

public class Main {
    public static void main(String[] args) {
        Set<User> users = new HashSet<>();

        users.add(new User(101, "Alice"));
        users.add(new User(101, "Alice"));

        System.out.println(users.size());
    }
}

Because the two User objects have the same ID and the equality contract treats the ID as the identity of the user, the HashSet considers them equal.

When Should You Use HashSet?

HashSet is useful when the primary requirement is maintaining a collection of unique values and performing membership checks efficiently.

  • You need to prevent duplicate values.
  • You frequently need to check whether a value exists.
  • Ordering is not required.
  • You need to remove duplicates from another collection.
  • You need to perform operations such as union, intersection, or difference.
  • You are solving coding problems involving unique values or membership checks.

Practical Example: Finding Duplicate Values

A HashSet can be used to detect duplicates while traversing an array. If adding an element returns false, that value has already been encountered.

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

public class Main {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 20, 40, 10};

        Set<Integer> seen = new HashSet<>();

        for (int number : numbers) {
            if (!seen.add(number)) {
                System.out.println("Duplicate: " + number);
            }
        }
    }
}

This approach can detect duplicates in average O(n) time because each HashSet insertion is typically O(1).

HashSet vs TreeSet

If unique elements must also remain sorted, TreeSet may be more appropriate than HashSet.

Feature HashSet TreeSet
Duplicates Not allowed Not allowed
Ordering No guaranteed order Sorted order
contains() O(1) average O(log n)
Primary purpose Fast unique-value operations Sorted unique values

Common HashSet Mistakes

  • Expecting HashSet to preserve insertion order.
  • Trying to access HashSet elements using indexes.
  • Using HashSet when duplicate values are intentionally required.
  • Using HashSet when sorted ordering is a requirement.
  • Assuming contains() is guaranteed O(1) in every possible condition.
  • Failing to implement equals() and hashCode() correctly for custom objects.
  • Modifying objects in ways that affect their equality or hash code while they are stored in the set.
  • Using a HashSet when a HashMap is needed to associate keys with values.

Key Takeaways

  • HashSet stores unique elements.
  • Duplicate values are automatically ignored.
  • add() returns false when the element already exists.
  • contains() is typically O(1) on average.
  • HashSet does not provide index-based access.
  • HashSet does not guarantee a predictable iteration order.
  • A single null element is permitted.
  • Custom objects should correctly implement equals() and hashCode().
  • Use TreeSet instead when unique elements also need to remain sorted.

Code Examples

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

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

        languages.add("Java");
        languages.add("Python");
        languages.add("Java");

        System.out.println(languages);
    }
}
    
import java.util.HashSet;
import java.util.Set;

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

        skills.add("Java");
        skills.add("C#");
        skills.add("Python");

        System.out.println(skills.contains("Java"));

        skills.remove("C#");

        System.out.println(skills);
    }
}
    
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();

        numbers.add(10);
        numbers.add(20);
        numbers.add(10);
        numbers.add(30);
        numbers.add(20);

        Set<Integer> uniqueNumbers = new HashSet<>(numbers);

        System.out.println(uniqueNumbers);
    }
}
    
import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        int[] numbers = {10, 20, 30, 20, 40, 10};

        Set<Integer> seen = new HashSet<>();

        for (int number : numbers) {
            if (!seen.add(number)) {
                System.out.println("Duplicate: " + number);
            }
        }
    }
}
    

Pro Tip

Use HashSet when uniqueness and fast membership checks are more important than ordering. If you need sorted unique values, consider TreeSet; if you need key-value relationships, use HashMap; and if you need indexed access with duplicates, use ArrayList.

🎨 IgKnight Docs

Master HTML, CSS, JS, Python, .NET and more with easy-to-follow lessons and practical code examples.

© 2025 IgKnight Learning Platform. All rights reserved.