Java 8 – Create an Immutable List

Introduction

Immutable lists are a fundamental concept in programming, particularly useful when you need to ensure that the contents of a list cannot be modified after it has been created. This is especially important in multi-threaded environments where data consistency is crucial. While Java has traditionally provided ways to create immutable collections, Java 8 introduced new, more concise methods to achieve immutability, especially with the Stream API and the Collectors utility class. In this guide, we’ll explore different approaches to creating immutable lists in Java 8.

Table of Contents

  • Problem Statement
  • Solution Steps
  • Java Program
    • Creating an Immutable List with Collections.unmodifiableList()
    • Creating an Immutable List with Stream and Collectors.toUnmodifiableList()
    • Creating an Immutable List with List.of()
  • Advanced Considerations
  • Conclusion

Problem Statement

The task is to create a Java program that:

  • Creates an immutable list.
  • Attempts to modify the list, which should result in an exception.
  • Outputs the list and the result of the modification attempt.

Example 1:

  • Input: List of strings ["apple", "banana", "orange"]
  • Output: The immutable list remains unchanged, and any modification attempt throws an exception.

Solution Steps

  1. Create a List: Start with a list of elements that you want to make immutable.
  2. Convert the List to an Immutable List: Use one of the available methods in Java 8 to create an immutable list.
  3. Attempt to Modify the List: Try adding or removing elements to/from the list to demonstrate immutability.
  4. Display the Result: Print the original list and the outcome of the modification attempt.

Java Program

Creating an Immutable List with Collections.unmodifiableList()

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Java 8 - Create an Immutable List Using Collections.unmodifiableList()
 * Author: https://www.rameshfadatare.com/
 */
public class ImmutableListExample {

    public static void main(String[] args) {
        // Step 1: Create a mutable list
        List<String> fruits = Arrays.asList("apple", "banana", "orange");

        // Step 2: Convert the list to an immutable list
        List<String> immutableFruits = Collections.unmodifiableList(fruits);

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

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

Output

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

Explanation

  • The Arrays.asList() method creates a mutable list of strings.
  • The Collections.unmodifiableList() method wraps this list in an immutable list, which means any attempt to modify it will result in an UnsupportedOperationException.
  • The modification attempt (adding "grape") fails, demonstrating the list’s immutability.

Creating an Immutable List with Stream and Collectors.toUnmodifiableList()

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Java 8 - Create an Immutable List Using Stream and Collectors.toUnmodifiableList()
 * Author: https://www.rameshfadatare.com/
 */
public class ImmutableListWithStreams {

    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 list
        List<String> immutableFruits = fruitsStream.collect(Collectors.collectingAndThen(
            Collectors.toList(), Collections::unmodifiableList));

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

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

Output

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

Explanation

  • The Stream.of() method creates a stream of strings.
  • The Collectors.collectingAndThen() method is used in combination with Collectors.toList() to create an immutable list by first collecting the stream into a mutable list and then wrapping it with Collections.unmodifiableList().
  • The modification attempt (adding "grape") fails, confirming the list’s immutability.

Creating an Immutable List with List.of()

import java.util.List;

/**
 * Java 8 - Create an Immutable List Using List.of()
 * Author: https://www.rameshfadatare.com/
 */
public class ImmutableListWithListOf {

    public static void main(String[] args) {
        // Step 1: Create an immutable list using List.of()
        List<String> immutableFruits = List.of("apple", "banana", "orange");

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

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

Output

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

Explanation

  • The List.of() method creates an immutable list directly, with no need for additional steps or methods.
  • Any modification attempt, such as adding an element, results in an UnsupportedOperationException, demonstrating the list’s immutability.

Advanced Considerations

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

  • Memory Efficiency: The immutability of lists can lead to memory efficiency, as the same immutable list can be shared across multiple parts of an application without the risk of accidental modification.

  • Performance Considerations: Creating an immutable list using List.of() or Collections.unmodifiableList() is generally efficient. However, if you have a large collection of elements, consider the impact on performance when converting a mutable list to an immutable one.

Conclusion

This guide provides methods for creating immutable lists in Java 8, covering approaches with Collections.unmodifiableList(), Stream and Collectors, and the concise List.of() method. Immutable lists 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