In Java 10, a significant enhancement was introduced to the java.util.stream.Collectors
class: new utility methods to create unmodifiable collections such as lists and sets. One notable method is Collectors.toUnmodifiableList()
. This method allows you to efficiently create immutable lists during stream processing, adding to the immutability features provided by Java 9 and earlier versions.
Here’s how you can use Collectors.toUnmodifiableList()
and other similar methods introduced in Java 10:
1. Using Collectors.toUnmodifiableList()
The Collectors.toUnmodifiableList()
collector creates an unmodifiable list from a stream of elements. This means the resulting list cannot be modified (no adding, removing, or updating elements). If you attempt to modify it, a runtime exception (UnsupportedOperationException
) will be thrown.
Example:
package org.kodejava.util.stream;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class UnmodifiableList {
public static void main(String[] args) {
// Example list using Collectors.toUnmodifiableList
List<String> unmodifiableList = Stream.of("A", "B", "C")
.collect(Collectors.toUnmodifiableList());
System.out.println("Unmodifiable List: " + unmodifiableList);
// Attempt to modify the list will throw UnsupportedOperationException
unmodifiableList.add("D"); // This will throw a runtime exception!
}
}
Output:
Unmodifiable List: [A, B, C]
Exception in thread "main" java.lang.UnsupportedOperationException
2. Other Collectors Introduced in Java 10
Java 10 introduced two other collectors similar to toUnmodifiableList()
:
Collectors.toUnmodifiableSet()
- Creates an unmodifiable set from a stream of elements.
- Duplicate elements will be removed since it’s a set.
Example:
package org.kodejava.util.stream;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class UnmodifiableSet {
public static void main(String[] args) {
Set<String> unmodifiableSet = Stream.of("A", "B", "C", "A") // "A" will appear only once
.collect(Collectors.toUnmodifiableSet());
System.out.println("Unmodifiable Set: " + unmodifiableSet);
unmodifiableSet.add("D"); // Throws UnsupportedOperationException
}
}
Collectors.toUnmodifiableMap()
- Creates an unmodifiable map using key-value pairs from a stream.
- Requires a way to specify the key and value in the collector.
- If duplicate keys are produced, it will throw an
IllegalStateException
.
Example:
package org.kodejava.util.stream;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class UnmodifiableMap {
public static void main(String[] args) {
Map<Integer, String> unmodifiableMap = Stream.of("A", "B", "C")
.collect(Collectors.toUnmodifiableMap(
String::length, // Key mapper
v -> v // Value mapper
));
System.out.println("Unmodifiable Map: " + unmodifiableMap);
// Attempting to modify will throw an UnsupportedOperationException
unmodifiableMap.put(2, "D"); // Throws UnsupportedOperationException
}
}
3. Behavior of Unmodifiable Collections
- These collectors guarantee that:
- The collection cannot be modified (no
add
,remove
,put
, etc.). - Any attempt to modify them results in an
UnsupportedOperationException
. - They are safe to use for read-only purposes.
- The collection cannot be modified (no
- If the stream itself contains null values, a
NullPointerException
will be thrown.
4. Best Uses of toUnmodifiable*()
Collectors
- Ensuring immutability for collections to prevent accidental modifications.
- Useful in multi-threaded or concurrent applications where immutability eliminates thread-safety issues.
- Perfect for cases where only read access is required.
5. Comparison with Java 9 List.of()
Java 9 introduced factory methods like List.of()
, Set.of()
, and Map.of()
for creating immutable collections. While those methods are concise, the new collectors offer more flexibility when working with streams.
Java 9 Example:
List<String> immutableList = List.of("A", "B", "C");
Java 10 Stream Example:
List<String> immutableList = Stream.of("A", "B", "C")
.collect(Collectors.toUnmodifiableList());
Summary Table:
Collector | Description | Introduced in |
---|---|---|
Collectors.toUnmodifiableList() |
Creates an unmodifiable List |
Java 10 |
Collectors.toUnmodifiableSet() |
Creates an unmodifiable Set |
Java 10 |
Collectors.toUnmodifiableMap() |
Creates an unmodifiable Map |
Java 10 |
Conclusion
The Collectors.toUnmodifiableList()
and related methods introduced in Java 10 are powerful tools for creating immutable collections directly from streams. They ensure immutability, improve code safety, and fit well into functional programming paradigms introduced with Java Streams.