Java HashSet Class


In Java, the HashSet class is one of the most commonly used implementations of the Set interface. It provides a collection that does not allow duplicate elements and does not guarantee any specific order. It is backed by a hash table, making it a highly efficient choice for situations where uniqueness is important, but ordering is not.


What is Java HashSet?

The HashSet class is part of the java.util package and implements the Set interface. It is designed to store unique elements, and it uses a hash table for its internal data structure. The HashSet class allows for constant time performance for basic operations like add(), remove(), and contains(), assuming the hash function disperses the elements properly.

Key Characteristics of HashSet:

  • No Duplicates: A HashSet does not allow duplicate elements.
  • Unordered: The elements in a HashSet are not stored in any predictable order. It does not guarantee the order of elements.
  • Null Element: Allows at most one null element.

Core Features of HashSet

Here are some of the main features of HashSet:

  • No Order Guarantee: The elements in a HashSet are stored in an unordered manner. If you need to maintain the insertion order, use LinkedHashSet.
  • Constant-Time Performance: Basic operations like adding, removing, and checking for elements (e.g., add(), remove(), contains()) typically run in constant time O(1).
  • Unique Elements: HashSet ensures that no duplicate elements are stored, meaning the collection will automatically eliminate any repeated values.
  • Thread-Unsafe: HashSet is not thread-safe by default. If you need a thread-safe version, you can use Collections.synchronizedSet() to wrap it, or consider using a ConcurrentHashMap.

Common Methods in HashSet

The HashSet class inherits methods from the Set interface. Below are some commonly used methods:

1. add(E e)

Adds an element to the set. If the element already exists, it will not be added (i.e., duplicates are ignored).

boolean add(E e);

2. remove(Object o)

Removes the specified element from the set.

boolean remove(Object o);

3. contains(Object o)

Checks if the set contains the specified element.

boolean contains(Object o);

4. size()

Returns the number of elements in the set.

int size();

5. isEmpty()

Checks if the set is empty.

boolean isEmpty();

6. clear()

Removes all elements from the set.

void clear();

7. iterator()

Returns an iterator over the elements in the set.

Iterator<E> iterator();

8. forEach(Consumer<? super E> action)

Performs the given action for each element in the set.

void forEach(Consumer<? super E> action);

Example: Using HashSet in Java

Here is an example demonstrating how to use HashSet in Java:

import java.util.*;

public class HashSetExample {
    public static void main(String[] args) {
        // Create a HashSet to store unique elements
        Set<String> fruits = new HashSet<>();

        // Add elements to the set
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Orange");
        fruits.add("Apple");  // Duplicate, will not be added

        // Check if a specific element exists
        System.out.println("Contains 'Banana': " + fruits.contains("Banana")); // true

        // Print all elements in the set
        System.out.println("Fruits in the HashSet: " + fruits); // Output: [Apple, Banana, Orange]

        // Remove an element
        fruits.remove("Orange");
        System.out.println("Fruits after removal: " + fruits); // Output: [Apple, Banana]

        // Get the size of the set
        System.out.println("Size of the set: " + fruits.size()); // Output: 2

        // Check if the set is empty
        System.out.println("Is the set empty? " + fruits.isEmpty()); // false

        // Iterate over the set using forEach
        fruits.forEach(fruit -> System.out.println(fruit)); // Output: Apple, Banana (order may vary)

        // Clear the set
        fruits.clear();
        System.out.println("Fruits after clearing: " + fruits); // Output: []
    }
}

Output:

Contains 'Banana': true
Fruits in the HashSet: [Apple, Banana, Orange]
Fruits after removal: [Apple, Banana]
Size of the set: 2
Is the set empty? false
Apple
Banana
Fruits after clearing: []

Explanation:

  • add() ensures that Apple is only added once, even though it was attempted twice.
  • contains() checks if the set contains the specified element, like Banana.
  • remove() removes Orange from the set.
  • size() gives the number of elements currently in the set.
  • isEmpty() checks if the set is empty.
  • forEach() allows iteration over the elements using a lambda expression.
  • clear() clears all elements in the set.

When to Use HashSet

You should consider using HashSet in Java when:

  1. Unique Elements: You need to store a collection of unique elements and don’t care about their order.
  2. Efficient Lookups: When you need constant time performance for basic operations like adding, checking existence, or removing elements.
  3. No Null Order: You don’t need to maintain any order of the elements, and you're fine with the elements being unordered.
  4. Thread-Unsafe Requirement: When you do not need thread-safety (or plan to implement it manually).

HashSet vs LinkedHashSet vs TreeSet

Feature HashSet LinkedHashSet TreeSet
Order No order. Maintains insertion order. Sorts elements in ascending order.
Performance O(1) for add, remove, contains (average). O(1) for add, remove, contains (average). O(log n) for add, remove, contains.
Null Elements Allows at most one null element. Allows at most one null element. Does not allow null elements.
Use Case Best for collections where order doesn’t matter. Best for collections where order matters (insertion order). Best for collections that require sorting.