Java HashSet

Introduction

The HashSet class in Java is a member of the Java Collections Framework and it extends the AbstractSet class and implements the Set interface.

Java HashSet

Key Points About HashSet Class

Unordered and Unsorted

The elements in a HashSet are not ordered or sorted. There is no guarantee that the order will remain constant over time.

Unique Elements

HashSet does not allow duplicate values. If you try to add the same value again, it will not replace the old value.

Null Elements

HashSet allows one null value.

Non-Synchronized

HashSet is non-synchronized, meaning it is not thread-safe and multiple threads can access it simultaneously.

Underlying Data Structure

HashSet is implemented in terms of a hash table and internally uses HashMap to store the elements.

Performance

The add, remove, and contains methods have constant time complexity O(1).

Implements Set Interface

HashSet implements the Set interface, inheriting all its methods.

Initial Capacity and Load Factor

The default initial capacity of HashSet is 16, and the default load factor is 0.75.

Create HashSet

Here is the syntax to create a HashSet class object:

// Creating a HashSet
HashSet<String> set = new HashSet<>();

Add Elements to HashSet

We can use the add() method to add elements to the HashSet:

import java.util.HashSet;

public class Main {
    public static void main(String[] args) {
        // Creating a HashSet
        HashSet<String> set = new HashSet<>();

        // Adding new elements to the HashSet
        set.add("Java");
        set.add("Python");
        set.add("JavaScript");

        // Displaying the HashSet elements
        for(String language : set){
            System.out.println(language);
        }
    }
}

Output:

Java
JavaScript
Python

HashSet Contains One Null Value but Not Duplicate Values

HashSet does not allow duplicate values and allows only one null value.

Here is a simple example that demonstrates this:

import java.util.HashSet;

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

        // Adding elements to the HashSet
        hset.add("Apple");
        hset.add("Mango");
        hset.add("Grapes");
        hset.add("Orange");
        hset.add("Fig");

        // Addition of duplicate elements
        hset.add("Apple");
        hset.add("Mango");

        // Addition of null values
        hset.add(null);
        hset.add(null);

        // Displaying HashSet elements
        System.out.println(hset);
    }
}

Output:

[null, Mango, Fig, Apple, Grapes, Orange]

Create HashSet from Another Collection

We can use the addAll() method to add all the elements from an existing collection to a HashSet.

Creating HashSet from Collection Example:

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> list = new ArrayList<>();
        list.add(5);
        list.add(10);
        list.add(15);
        list.add(20);
        list.add(25);

        List<Integer> list2 = new ArrayList<>();
        list2.add(3);
        list2.add(6);
        list2.add(9);
        list2.add(12);
        list2.add(15);

        // Creating a HashSet from another collection (ArrayList)
        Set<Integer> set = new HashSet<>(list);

        // Adding all the elements from an existing collection to a HashSet
        set.addAll(list2);

        System.out.println(set);
    }
}

Output:

[3, 5, 6, 9, 10, 12, 15, 20, 25]

Access Elements

In Java, the HashSet class does not have a get() method to access its elements as it is not an indexed collection. However, you can iterate through a HashSet to access its elements.

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

public class Main {
    public static void main(String[] args) {
        // Creating a HashSet
        HashSet<String> set = new HashSet<>();

        // Adding new elements to the HashSet
        set.add("Java");
        set.add("Python");
        set.add("JavaScript");

        // Accessing elements using an iterator
        Iterator<String> iterator = set.iterator();
        while(iterator.hasNext()){
            String language = iterator.next();
            System.out.println(language);
        }
    }
}

Output:

JavaScript
Java
Python

Remove Elements

We can remove elements from HashSet using these methods:

  • remove(Object o): This method removes a single specified element from the set.
  • removeAll(Collection c): This method removes all elements from the set that are contained in the specified collection.
  • removeIf(Predicate<? super E> filter): This method removes all elements from the set that satisfy the given predicate.
import java.util.HashSet;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        // Creating a HashSet
        HashSet<String> set = new HashSet<>();
        set.addAll(Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry"));

        System.out.println("Original HashSet: " + set);

        // Using remove(Object o)
        set.remove("Cherry");
        System.out.println("\nAfter remove('Cherry'): " + set);

        // Using removeAll(Collection c)
        set.removeAll(Arrays.asList("Apple", "Banana"));
        System.out.println("\nAfter removeAll(Arrays.asList('Apple', 'Banana')): " + set);

        // Using removeIf(Predicate<? super E> filter)
        set.removeIf(fruit -> fruit.startsWith("E"));
        System.out.println("\nAfter removeIf(fruit -> fruit.startsWith('E')): " + set);
    }
}

Output:

Original HashSet: [Date, Apple, Elderberry, Cherry, Banana]

After remove('Cherry'): [Date, Apple, Elderberry, Banana]

After removeAll(Arrays.asList('Apple', 'Banana')): [Date, Elderberry]

After removeIf(fruit -> fruit.startsWith('E')): [Date]

Iterate or Loop Through HashSet

Using Iterator

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

public class Main {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("element 1");
        set.add("element 2");
        set.add("element 3");
        set.add("element 4");

        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            String str = iterator.next();
            System.out.println(" only forward direction ---" + str);
        }
    }
}

Using Enhanced For Loop

public class Main {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("element 1");
        set.add("element 2");
        set.add("element 3");
        set.add("element 4");

        for (String str : set) {
            System.out.println(" only forward direction ---" + str);
        }
    }
}

Using forEachRemaining() Method (Java 8)

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

public class Main {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("element 1");
        set.add("element 2");
        set.add("element 3");
        set.add("element 4");

        Iterator<String> iterator = set.iterator();
        iterator.forEachRemaining(str -> System.out.println(" only forward direction ---" + str));
    }
}

Using forEach() Method (Java 8)

import java.util.HashSet;

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


        set.add("element 1");
        set.add("element 2");
        set.add("element 3");
        set.add("element 4");

        set.forEach(str -> System.out.println(" only forward direction ---" + str));
    }
}

HashSet with User-Defined Objects

This example shows how to create a HashSet of user-defined objects.

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

class Customer {
    private long id;
    private String name;

    public Customer(long id, String name) {
        this.id = id;
        this.name = name;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // Two customers are equal if their IDs are equal
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Customer customer = (Customer) o;
        return id == customer.id;
    }

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

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

public class Main {
    public static void main(String[] args) {
        Set<Customer> customers = new HashSet<>();
        customers.add(new Customer(1, "Ramesh"));
        customers.add(new Customer(2, "Pramod"));
        customers.add(new Customer(3, "Sanjay"));

        System.out.println(customers);
    }
}

Output:

[Customer{id=1, name='Ramesh'}, Customer{id=2, name='Pramod'}, Customer{id=3, name='Sanjay'}]

Make HashSet Thread-Safe

In Java, HashSet is not thread-safe, which means if it is used in a multi-threaded environment, then multiple threads can access and modify it simultaneously leading to data inconsistency. However, you can make a HashSet thread-safe by using the Collections.synchronizedSet() method.

Here is an example:

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

public class Main {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("Apple");
        set.add("Banana");
        set.add("Cherry");

        Set<String> synchronizedSet = Collections.synchronizedSet(set);

        // Now you can use synchronizedSet in a multi-threaded environment safely
    }
}

Conclusion

Congratulations folks! In this article, you learned what is a HashSet, key points about HashSet, how to create a HashSet, how to add elements to a HashSet, how to remove elements from the HashSet, how to iterate over a HashSet, and how to create a HashSet of user-defined objects.

Comments

  1. the usage of

    forEachRemaining()
    // Java 8
    list.forEachRemaining(str -> System.out.println(" only forward direction ---" + str));

    may not correct

    ReplyDelete
  2. if that have to instead of -> ?

    Iterator i = list.iterator();
    i.next();
    i.forEachRemaining(System.out::println);

    ReplyDelete

Post a Comment

Leave Comment