Collecting a Stream to an Immutable Collection in Java - GeeksforGeeks

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 10Creating Stream and collecting it into an unmodifiable structure using the “collectingAndThen”Google’s Guava libraryAfter Java 10toUnmodifiableList()toUnmodifiableMap()toUnmodifiableSet()
Pre-Java 10Creating Stream and collecting it into an unmodifiable structure using the “collectingAndThen”Google’s Guava library
Creating Stream and collecting it into an unmodifiable structure using the “collectingAndThen”
Google’s Guava library
After Java 10toUnmodifiableList()toUnmodifiableMap()toUnmodifiableSet()
toUnmodifiableList()
toUnmodifiableMap()
toUnmodifiableSet()
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
// Java Program to illustrate Collecting a Stream to an// Immutable Collection// Pre java 10// Using collectingAndThen method // Importing Collections, Collectors and Stream classes// from java.util packageimport java.util.Collections;import java.util.stream.Collectors;import java.util.stream.Stream; // Main class// PreJava10ImmutableCollectionspublic class GFG {     // Main driver method    public static void main(String[] args)    {         // Custom inputs integer elements in List        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);         // Operations like this will result in an exception        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
// Java Program to illustrate Collecting a// Stream to an Immutable Collection// Pre java 10  Using Google’s Guava library // Importing Guava libraryimport com.google.common.collect.ImmutableList;// Importing classes from java.util packageimport java.util.List;import java.util.stream.IntStream; // Main classpublic class PreJava10ImmutableCollections {     // main driver method    public static void main(String[] args) {         // Using the Guava Libraries        List<Integer> someList            = IntStream.range(0, 15).boxed().collect(                  ImmutableList.toImmutableList());         // Print and display the elements        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.
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
// Java Program to illustrate Collecting a Stream to// an Immutable Collection// Post java 10// using toUnmodifiableList() method // Importing classes from java.util packageimport java.util.List;import java.util.stream.Collectors;import java.util.stream.Stream; // Main Class// ImmutableCollectionListpublic class GFG {     // Main driver method    public static void main(String[] args)    {        // Creating Stream class object of integer type        Stream<Integer> evenNumberStream            = Stream.iterate(0, i -> i + 2).limit(50);         // Creating List class object of integer type        List<Integer> evenNumbers            = (List<Integer>)evenNumberStream.collect(                Collectors.toUnmodifiableList());         // Print all elements in the List object        System.out.println(evenNumbers);         // These will result in        // java.lang.UnsupportedOperationException         evenNumbers.add(90);        // evenNumbers.remove(1);    }}
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
// Java Program to illustrate Collecting a Stream to// an Immutable Collection// Post java 10// Using toUnmodifiableMap() method // Importing required librariesimport java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.stream.Collectors;import java.util.stream.Stream; // Main Class// ImmutableCollectionMappublic class GFG {     // Main driver method    public static void main(String[] args)    {         // Creating a Map from a Stream of books by        // creating an object of List class of books type        List<Books> libInventory = new ArrayList<Books>();         // Adding elements to the above object created        // Custom input entries        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"));         // Creating a Map class object        // Declaring object of integer and string type        Map<Integer, String> unmutableInventory            = libInventory.stream().collect(                Collectors.toUnmodifiableMap(                    Books::getBookNumber,                    Books::getBookName));         // Print all the elements in the Map object created        // above        System.out.println(unmutableInventory);         // This will result in an Exception        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
// Java Program to illustrate Collecting a Stream to// an Immutable Collection// Post java 10// Using toUnmodifiableSet() method // Importing required librariesimport java.util.Set;import java.util.stream.Collectors;import java.util.stream.Stream; // Main class// ImmutableCollectionSetpublic class GFG {     // Main driver method    public static void main(String[] args)    {        // Creating Stream object of type Double        Stream<Double> randomDecimals            = Stream.generate(Math::random).limit(30);         // Now creating Set class object of type Double        Set<Double> randomSet = randomDecimals.collect(            Collectors.toUnmodifiableSet());         // Print and display elements in Set object        System.out.println(randomSet);         // This will produce an exception        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.
sweetyty
arorakashish0911
prachisoda1234
Java-Collections
java-stream
Picked
Java
Java
Java-Collections
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Stream In Java
Constructors in Java
Different ways of Reading a text file in Java
Exceptions in Java
Functional Interfaces in Java
Generics in Java
Comparator Interface in Java with Examples
Introduction to Java
HashMap get() Method in Java
Strings in Java