How to make a Java collection unmodifiable?

As array support, fixed-size data and the size has to be calculated during the array initialization programming languages invented collections to overcome the limitation of the array. But as the use of collections increases the requirements also changed. i.e. A collection that has been created should not allow any modification to it. This is the need, which introduced the concept of unmodifiable collections.

Convenience static factory methods on the List, Set, and Map interfaces let you easily create unmodifiable lists, sets, and maps.

A collection is considered unmodifiable if elements cannot be added, removed, or replaced. After you create an unmodifiable instance of a collection, it holds the same data as long as a reference to it exists.

A modifiable collection must maintain bookkeeping data to support future modifications. This adds overhead to the data that is stored in the modifiable collection. An unmodifiable collection does not need this extra bookkeeping data. Because the collection never needs to be modified, the data contained in the collection can be packed much more densely. Unmodifiable collection instances generally consume much less memory than modifiable collection instances that contain the same data.

So when to use an unmodifiable collection?

Whether to use an unmodifiable collection or a modifiable collection depends on the data in the collection.
An unmodifiable collection provides space efficiency benefits and prevents the collection from accidentally being modified, which might cause the program to work incorrectly. An unmodifiable collection is recommended for the following cases:

  • Collections that are initialized from constants that are known when the program is written.
  • Collections that are initialized at the beginning of a program from data that is computed or is read from something such as a configuration file.

For a collection that holds data that is modified throughout the program, a modifiable collection is the best choice. Modifications are performed in-place so that incremental additions or deletions of data elements are quite inexpensive. If this were done with an unmodifiable collection, a complete copy would have to be made to add or remove a single element, which usually has unacceptable overhead.

Note: Making any change to the unmodifiable collection will cause “java.lang.UnsupportedOperationException”.

Let’s try an example to create an unmodifiable collection.

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

public class UnModifiableCollection {

	public static void main(String[] args) {
		List<String> list = new ArrayList<>(Arrays.asList("Temp","Dist","Demt","bin","Hello")) ;
		
		System.out.println("print 1 "+list);
		
		list.add("check");
		
		System.out.println("print 2 "+list);
		
		list = Collections.unmodifiableList(list);
		
		list.add("set"); // This line will prompt the Exception

		// This also creates fixed-size list backed by an array.
	    List<String> unmodifiable = Arrays.asList("Temp","Dist","Demt","bin","Hello"); 
	     
	     // unmodifiable.add("3232"); // Even this line will also prompt the same Exception. Uncomment it to verify. 

	}
}

If you run the above program the output will be like:

print 1 [Temp, Dist, Demt, bin, Hello]
print 2 [Temp, Dist, Demt, bin, Hello, check]
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
	at UnModifiableCollection.main(UnModifiableCollection.java:21)

The java.util.Collections class offers the following methods to create unmodifiable collections.

List of methods provided by Collections class to create unmodifiable collection

From Java 11 onward we can create an unmodifiable collection using the Java Stream API.

The Streams library includes a set of terminal operations known as Collectors. A Collector is most often used to create a new collection that contains the elements of the stream. The java.util.stream.The collectors class has Collectors that create new unmodifiable collections from the elements of the streams.
If you want to guarantee that the returned collection is unmodifiable, you should use one of them toUnmodifiable- collectors. These collectors are:

Collectors.toUnmodifiableList()
Collectors.toUnmodifiableSet()
Collectors.toUnmodifiableMap(keyMapper, valueMapper)
Collectors.toUnmodifiableMap(keyMapper, valueMapper, mergeFunction)

Recommended Read

ArrayList vs LinkedList
Java 8 Default and Static method in Interface

Happy Learning !!