Java 8 – Create an Immutable Set

Introduction

In Java, an immutable set is a set whose elements cannot be modified after the set is created. Immutable sets are useful in scenarios where you want to ensure that the data remains constant and is not accidentally altered. This can be particularly important in multi-threaded environments where data consistency is crucial. While Java 8 does not have a built-in Set.of() method like later versions (Java 9+), you can still create immutable sets using various techniques. In this guide, we’ll explore how to create an immutable set in Java 8.

Table of Contents

  • Problem Statement
  • Solution Steps
  • Java Program
    • Creating an Immutable Set with Collections.unmodifiableSet()
    • Creating an Immutable Set from a Stream
    • Creating an Immutable Set from an Existing Set
  • Advanced Considerations
  • Conclusion

Problem Statement

The task is to create a Java program that:

  • Creates a Set of elements.
  • Converts the Set to an immutable set.
  • Attempts to modify the set and handles the exception if the set is immutable.

Example:

  • Input: Set of strings ["apple", "banana", "orange"]
  • Output: Immutable set ["apple", "banana", "orange"] and a demonstration that modifying the set results in an exception.

Solution Steps

  1. Create a Mutable Set: Start with a mutable Set of elements.
  2. Convert the Set to an Immutable Set: Use one of the methods available in Java 8 to make the set immutable.
  3. Attempt to Modify the Set: Try adding or removing elements from the set to demonstrate its immutability.
  4. Display the Result: Print the original set and the outcome of the modification attempt.

Java Program

Creating an Immutable Set with Collections.unmodifiableSet()

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

/**
 * Java 8 - Create an Immutable Set Using Collections.unmodifiableSet()
 * Author: https://www.rameshfadatare.com/
 */
public class ImmutableSetExample {

    public static void main(String[] args) {
        // Step 1: Create a mutable set
        Set<String> fruits = new HashSet<>();
        fruits.add("apple");
        fruits.add("banana");
        fruits.add("orange");

        // Step 2: Convert the set to an immutable set
        Set<String> immutableFruits = Collections.unmodifiableSet(fruits);

        // Step 3: Attempt to modify the set (this should throw an exception)
        try {
            immutableFruits.add("grape");
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot modify the immutable set.");
        }

        // Step 4: Display the result
        System.out.println("Immutable Set: " + immutableFruits);
    }
}

Output

Cannot modify the immutable set.
Immutable Set: [banana, orange, apple]

Explanation

  • The Collections.unmodifiableSet() method is used to wrap the original mutable set into an immutable set.
  • Any attempt to modify the immutable set (such as adding "grape") results in an UnsupportedOperationException, demonstrating the set’s immutability.
  • The original elements ["banana", "orange", "apple"] are preserved in the immutable set.

Creating an Immutable Set from a Stream

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Java 8 - Create an Immutable Set from a Stream
 * Author: https://www.rameshfadatare.com/
 */
public class ImmutableSetFromStream {

    public static void main(String[] args) {
        // Step 1: Create a stream of elements
        Stream<String> fruitsStream = Stream.of("apple", "banana", "orange");

        // Step 2: Convert the stream to an immutable set
        Set<String> immutableFruits = fruitsStream
                                        .collect(Collectors.collectingAndThen(
                                            Collectors.toSet(),
                                            Collections::unmodifiableSet));

        // Step 3: Attempt to modify the set (this should throw an exception)
        try {
            immutableFruits.add("grape");
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot modify the immutable set.");
        }

        // Step 4: Display the result
        System.out.println("Immutable Set: " + immutableFruits);
    }
}

Output

Cannot modify the immutable set.
Immutable Set: [banana, orange, apple]

Explanation

  • The Stream.of() method is used to create a stream of strings.
  • The Collectors.collectingAndThen() method is used to first collect the stream into a mutable set and then wrap it with Collections.unmodifiableSet() to make it immutable.
  • Any modification attempt, such as adding an element, results in an UnsupportedOperationException, confirming the set’s immutability.

Creating an Immutable Set from an Existing Set

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

/**
 * Java 8 - Create an Immutable Set from an Existing Set
 * Author: https://www.rameshfadatare.com/
 */
public class ImmutableSetFromExistingSet {

    public static void main(String[] args) {
        // Step 1: Create an existing mutable set
        Set<String> fruits = new HashSet<>();
        fruits.add("apple");
        fruits.add("banana");
        fruits.add("orange");

        // Step 2: Convert the existing set to an immutable set
        Set<String> immutableFruits = Collections.unmodifiableSet(new HashSet<>(fruits));

        // Step 3: Attempt to modify the set (this should throw an exception)
        try {
            immutableFruits.add("grape");
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot modify the immutable set.");
        }

        // Step 4: Display the result
        System.out.println("Immutable Set: " + immutableFruits);
    }
}

Output

Cannot modify the immutable set.
Immutable Set: [banana, orange, apple]

Explanation

  • The Collections.unmodifiableSet() method is used to create an immutable set from an existing mutable set.
  • The modification attempt fails, demonstrating that the set cannot be changed once it has been made immutable.

Advanced Considerations

  • Thread Safety: Immutable sets are inherently thread-safe because their contents cannot change after creation. This makes them an excellent choice in concurrent programming.

  • Memory Efficiency: Immutable sets can lead to memory efficiency, as the same immutable set can be shared across multiple parts of an application without the risk of accidental modification.

  • Performance Considerations: Creating an immutable set using Collections.unmodifiableSet() or Collectors.collectingAndThen() is generally efficient. However, consider the performance impact when working with very large sets.

Conclusion

This guide provides methods for creating an immutable set in Java 8, covering approaches with Collections.unmodifiableSet() and the Stream API. Immutable sets are crucial for ensuring data consistency and preventing unintended modifications, especially in multi-threaded environments. Depending on your specific use case, you can choose the method that best fits your needs for creating immutable collections in Java.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top