Collecting a Stream to an Immutable Collection in Java
Last Updated :
25 Oct, 2021
Streams and Collectors were introduced in Java 8 introduced the concept of Streams. A Stream is a sequence, a sequence of objects. We generate Streams from input sources like Arrays, Lists, etc., and support aggregation operations like filter, map, limit, reduce, etc. We use Streams to pipeline data and ultimately collect it into some form of a Collector. A Collector is nothing but the container used to store the result of the Stream processing. A Collector could be a List, Map, or a Set.
An Immutable collection is a collection whose values we cannot change once created. We do need immutable Collections because many times we can have Collections of data that do not change, i.e., Lookup lists. For example, a list of months in a year or days of the week, etc. Making such lists(which have data that does not change) immutable makes them more memory and space-efficient. They are also inherently thread-safe. Immutable objects, in general, require much less memory than their mutable counterparts.
An object is considered immutable if its state cannot change after it is constructed. After you create an immutable instance of a collection, it holds the same data as long as a reference to it exists.
Methods: Depending on the Java version, multiple methods are available for creating immutable objects as per advancement in versions of java with which we can create Immutable Collections.
- Pre-Java 10
- Creating Stream and collecting it into an unmodifiable structure using the “collectingAndThen”
- Google’s Guava library
- After Java 10
- toUnmodifiableList()
- toUnmodifiableMap()
- toUnmodifiableSet()
Scenario 1: Pre-Java 10
Method 1: Creating Stream and collecting it into an unmodifiable structure. Before, Java 10 there was no direct way to create an immutable collection in Java. One method was creating a Stream and collecting it into an unmodifiable structure using the “collectingAndThen” method.
Example:
Java
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class GFG {
public static void main(String[] args)
{
var unmodifiableList
= Stream.of( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 )
.collect(Collectors.collectingAndThen(
Collectors.toList(),
Collections::unmodifiableList));
System.out.println(unmodifiableList);
unmodifiableList.add( 12 );
}
}
|
Output:
Method 2: Using Google’s Guava library. For this, a pre-requisite work is required which is to include the JAR file. The JAR for the Guava library is to download the jar and add it to the build path in eclipse. The Guava Library provides the ImmutableList class. An example of the same is given below.
Example:
Java
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.stream.IntStream;
public class PreJava10ImmutableCollections {
public static void main(String[] args) {
List<Integer> someList
= IntStream.range( 0 , 15 ).boxed().collect(
ImmutableList.toImmutableList());
System.out.println(someList);
}
}
|
Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Note: We can also implement our own version of making an immutable list or map or set.
Scenario 2: Java version 10 and above
Java version 10 introduced functions to create Immutable collections through the Collectors class. We have 3 methods, one for List, one for Set, and one for Map.
Method 1: Using toUnmodifiableList() method. Assume we have a Stream of the first 50 even numbers and create an immutable List from it.
Example:
Java
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class GFG {
public static void main(String[] args)
{
Stream<Integer> evenNumberStream
= Stream.iterate( 0 , i -> i + 2 ).limit( 50 );
List<Integer> evenNumbers
= (List<Integer>)evenNumberStream.collect(
Collectors.toUnmodifiableList());
System.out.println(evenNumbers);
evenNumbers.add( 90 );
}
}
|
Output:
Method 2: Using toUnmodifiableMap() Method
Consider an example of a Books class. The Books object has two parameters namely ‘Id’ and ‘Name’. We will generate a Stream of book Objects. Assume that we have to generate an immutable Map from this collection of Objects. To do so, we use the toUnmodifiableMap() function.
Example:
Java
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class GFG {
public static void main(String[] args)
{
List<Books> libInventory = new ArrayList<Books>();
libInventory.add(
new Books( 1 , "Pride and Prejudice" ));
libInventory.add( new Books( 2 , "The Sign of Four" ));
libInventory.add(
new Books( 3 , "Sense and Sensibility" ));
libInventory.add( new Books( 4 , "Mansfield Park" ));
libInventory.add(
new Books( 5 , "The Materese Circle" ));
libInventory.add(
new Books( 6 , "The Hound of Baskerville" ));
libInventory.add( new Books( 7 , "Goodnight Moon" ));
libInventory.add( new Books(
8 , "How many sleeps till my Birthday" ));
libInventory.add(
new Books( 9 , "The Bourne Identity" ));
libInventory.add( new Books( 10 , "Murder She Wrote" ));
libInventory.add( new Books(
11 , "The adventures of Hercule Poirot" ));
libInventory.add(
new Books( 12 , "The song of Ice and Fire" ));
Map<Integer, String> unmutableInventory
= libInventory.stream().collect(
Collectors.toUnmodifiableMap(
Books::getBookNumber,
Books::getBookName));
System.out.println(unmutableInventory);
unmutableInventory.put( 13 , "Some book" );
}
}
|
Output:
Method 3: Using toUnmodifiableSet() method
Implementation: Creating an unmodifiable Set from a stream to do so, we use the toUnmodifiableSet() function.
Java
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class GFG {
public static void main(String[] args)
{
Stream<Double> randomDecimals
= Stream.generate(Math::random).limit( 30 );
Set<Double> randomSet = randomDecimals.collect(
Collectors.toUnmodifiableSet());
System.out.println(randomSet);
randomSet.add( 100.0 );
}
}
|
Conclusion: Here we have seen how to create Immutable Collections from a Stream in Java. We also saw the different methods used to create the Collections based on the Java version being used.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...