The implementation of toList() clearly returns an ArrayList which does guarantee mutability:
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>(ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
but the JavaDoc of toList reads as:
/**
* Returns a {@code Collector} that accumulates the input elements into a
* new {@code List}. There are no guarantees on the type, mutability,
* serializability, or thread-safety of the {@code List} returned; if more
* control over the returned {@code List} is required, use {@link #toCollection(Supplier)}.
*
* @param <T> the type of the input elements
* @return a {@code Collector} which collects all the input elements into a
* {@code List}, in encounter order
*/
Why is mutability not guaranteed? Am I missing cases where the returned collection could be immutable? is it safe to use Collectors.toList() when mutability is required of the returned collection?
Because the authors said so
Because the designers of the
Collectors.toListmethod chose so.That fact is a mere implementation detail.
And that detail applies only to the one version of the one implementation that you studied. Other versions, and other implementations, may use something other than
ArrayList.Any implementation is subject to change, within the limits of the contract promised by the documentation. All that matters is the behavior promised by that documentation.
To quote the Javadoc:
Seems crystal clear to me. You have been promised that the resulting
Listmay be mutable or may be immutable. You’ve been told not to rely on either being the case.Modifiable
If you want a mutable/modifiable
List, make a new one from the list generated by your collector. Pass the collected list to the constructor of a new list object.Or, as the Javadoc above suggests, you can pass
Supplierto render a list implementation of your choice. CallCollectors.toCollection. See section 3.3 of the tutorial on Baeldung.com.For example:
Unmodifiable
If you want an immutable/unmodifiable list, I suggest calling
List.copyOf.That method promises to return:
But there is a catch: No nulls allowed. Two alternatives for a list with nulls:
Stream#toListfor an unmodifiable list tolerating nulls.Collections.unmodifiableList.By the way, Java 21 brought sequenced collections. So the more general interface of
ListisSequencedCollection.