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
- Creating an Immutable Set with
- 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
- Create a Mutable Set: Start with a mutable
Set
of elements. - Convert the Set to an Immutable Set: Use one of the methods available in Java 8 to make the set immutable.
- Attempt to Modify the Set: Try adding or removing elements from the set to demonstrate its immutability.
- 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 anUnsupportedOperationException
, 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 withCollections.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()
orCollectors.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.