Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collectors.toUnmodifiableList vs Collections.unmodifiableList in Java 10

As per the doc the method Collections.unmodifiableList returns an unmodifiable view of the specified list. Is the list returned truly unmodifiable? What do we mean by unmodifiable view?

As per doc the method Collectors.toUnmodifiableList returns a Collector that accumulates the input elements into an unmodifiable List in encounter order. Is the list returned here truly unmodifiable?

Note: By modifiable I mean the view can be modified by using set operation. I want to understand the difference and how are they related?

like image 535
rakhi Avatar asked Oct 03 '18 05:10

rakhi


Video Answer


2 Answers

The method Collections.unmodifiableList returns an unmodifiable view of the specified list. An unmodifiable view collection is a collection that is unmodifiable and is also a view onto a backing collection. Note that changes to the backing collection might still be possible, and if they occur, they are visible through the unmodifiable view.

List<String> srcList = Arrays.asList("Apple", "Banana", "Cherry");
var fruits = new ArrayList<>(srcList);
var unmodifiableList = Collections.unmodifiableList(fruits);     
fruits.set(0, "Apricot");
var modFruit = unmodifiableList.get(0);
System.out.println(modFruit); // prints Apricot

We can have a true immutable list in Java 10 and later. There are two ways to get truly unmodifiable list as shown below:

  1. var unmodifiableList = List.copyOf(srcList); => prints Apple
  2. var unmodifiableList = srcList.stream().collect(Collectors.toUnmodifiableList()); => prints Apple

So the method Collectors.toUnmodifiableList returns a true unmodifiable list List.of introduced in Java 9. This method returns a Collector where as the method Collections.unmodifiableList returns a list. As per doc the unmodifiable lists has following characteristics:

  1. They are unmodifiable. Elements cannot be added, removed, or replaced. Calling any mutator method on the List will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the List's contents to appear to change.
  2. They disallow null elements. Attempts to create them with null elements result in NullPointerException.
  3. They are serializable if all elements are serializable.
  4. The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.
  5. They are value-based. Callers should make no assumptions about the identity of the returned instances. Factories are free to create new instances or reuse existing ones. Therefore, identity-sensitive operations on these instances (reference equality (==), identity hash code, and synchronization) are unreliable and should be avoided.
  6. They are serialized as specified on the Serialized Form page.
like image 115
akhil_mittal Avatar answered Nov 04 '22 06:11

akhil_mittal


Collections.unmodifiableList returns an unmodifiable view, which means calling any methods of the returned List that mutate the List would throw UnsupportedOperationException. However, the original List that was passed to that method can still be modified (assuming it is modifiable), and such modifications will be reflected in the List returned by Collections.unmodifiableList. Therefore, it can only be considered "truly unmodifiable" if you don't have access to the original List.

Collectors.toUnmodifiableList, on the other hand, is used to generate a new List which is unmodifiable, so there is no way to modify that List. Therefore it is "truly unmodifiable".

like image 26
Eran Avatar answered Nov 04 '22 05:11

Eran