Iterating over a HashSet in Java

A HashSet is a collection that implements the Set interface, backed by a HashMap. It stores elements in no particular order and does not allow duplicates. This guide will provide examples of how to iterate over a HashSet using different methods, including detailed explanations and outputs. Additionally, it will cover how to iterate over a HashSet containing custom objects.

Table of Contents

  1. Introduction
  2. Using Enhanced For-Loop
  3. Using Iterator
  4. Using forEach Method (Java 8)
  5. Using Stream API (Java 8)
  6. Iterating Over a HashSet with Custom Objects
  7. Conclusion

1. Introduction

A HashSet is a part of the Java Collections Framework and is an implementation of the Set interface that does not allow duplicate elements. It is useful for scenarios where you need a set that ensures uniqueness without any specific ordering.

2. Using Enhanced For-Loop

The enhanced for-loop (or for-each loop) provides a simple and readable way to iterate over a HashSet.

Example: Using Enhanced For-Loop

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

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

        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}

Output:

Apple
Banana
Orange

3. Using Iterator

The Iterator provides a way to iterate over the elements and allows element removal during iteration if needed.

Example: Using Iterator

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

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

        Iterator<String> iterator = fruits.iterator();
        while (iterator.hasNext()) {
            String fruit = iterator.next();
            System.out.println(fruit);
        }
    }
}

Output:

Apple
Banana
Orange

4. Using forEach Method (Java 8)

The forEach method is part of the Java 8 Stream API and provides a functional approach to iteration.

Example: Using forEach Method

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

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

        // Using forEach with lambda expression
        fruits.forEach(fruit -> System.out.println(fruit));

        // Using forEach with method reference
        fruits.forEach(System.out::println);
    }
}

Output:

Apple
Banana
Orange

5. Using Stream API (Java 8)

The Stream API provides a powerful way to process sequences of elements, including iteration.

Example: Using Stream API

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

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

        // Using stream and forEach
        fruits.stream().forEach(fruit -> System.out.println(fruit));

        // Using parallel stream and forEach
        fruits.parallelStream().forEach(fruit -> System.out.println("Parallel: " + fruit));
    }
}

Output:

Apple
Banana
Orange
Parallel: Apple
Parallel: Banana
Parallel: Orange

6. Iterating Over a HashSet with Custom Objects

When dealing with custom objects in a HashSet, it is important to override the equals and hashCode methods to ensure the uniqueness of the elements. Here is an example using a custom Person class.

Custom Object Example: Using Enhanced For-Loop

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

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return name.hashCode() * 31 + age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + '}';
    }
}

public class CustomObjectExample {
    public static void main(String[] args) {
        Set<Person> persons = new HashSet<>();
        persons.add(new Person("Alice", 30));
        persons.add(new Person("Bob", 25));
        persons.add(new Person("Charlie", 35));

        // Using Enhanced For-Loop
        System.out.println("Using Enhanced For-Loop:");
        for (Person person : persons) {
            System.out.println(person);
        }

        // Using Iterator
        System.out.println("\nUsing Iterator:");
        Iterator<Person> iterator = persons.iterator();
        while (iterator.hasNext()) {
            Person person = iterator.next();
            System.out.println(person);
        }

        // Using forEach Method (Java 8)
        System.out.println("\nUsing forEach Method (Java 8):");
        persons.forEach(person -> System.out.println(person));

        // Using Stream API (Java 8)
        System.out.println("\nUsing Stream API (Java 8):");
        persons.stream().forEach(person -> System.out.println(person));
    }
}

Output:

Using Enhanced For-Loop:
Person{name='Alice', age=30}
Person{name='Bob', age=25}
Person{name='Charlie', age=35}

Using Iterator:
Person{name='Alice', age=30}
Person{name='Bob', age=25}
Person{name='Charlie', age=35}

Using forEach Method (Java 8):
Person{name='Alice', age=30}
Person{name='Bob', age=25}
Person{name='Charlie', age=35}

Using Stream API (Java 8):
Person{name='Alice', age=30}
Person{name='Bob', age=25}
Person{name='Charlie', age=35}

7. Conclusion

In this guide, we covered various methods to iterate over a HashSet in Java:

  • Using Enhanced For-Loop: Simplifies code and improves readability.
  • Using Iterator: Allows element removal during iteration.
  • Using forEach Method (Java 8): Provides a functional programming approach.
  • Using Stream API (Java 8): Offers powerful operations for processing sequences of elements, including parallel processing.

Additionally, we demonstrated how to iterate over a HashSet containing custom objects, ensuring the proper implementation of equals and hashCode methods for correct behavior in a set.

Comments