There is a list of Person
objects.
List<Person> persons = generatePersons();
An unmodifiableList is created with it.
List<Person> unmodifiableList = Collections.unmodifiableList(persons);
I understand that unmodifiableList
doesn't support add/remove/set operations. At the same time it is not immutable since it has a reference to an existing modifiable list persons
and whenever changes are made to the persons
list, the changes are reflected in unmodifiableList
too.
An immutable list is created this way.
List<Person> immutableList = Collections.unmodifiableList(new ArrayList<>(persons));
This creates an immutable list since a conversion constructor is being used. No add/remove/set ops can be performed on immutableList
nor any change in the original list persons
would reflect in immutableList
.
Let's make an assumption that Person
objects are immutable too.
Now, I want to create these two lists using streams.
The first one, I have created using:
List<Person> unmodifiablePersons = persons.stream()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
I am lost at creating equivalent of immutableList through streams.
How can I do that?
Edit:
I added a new Person
object to the original list persons
and printed the size of persons
list and unmodifiablePersons
. Both give me the same size.
So, changes are being reflected to unmodifiablePersons
and hence it is not immutable yet. Am I missing something here?
Edit 2
Silly. Should have gone through the docs. unmodifiablePersons
is indeed an immutable list. Also, the new Person
object was added before the unmodifiablePersons
was created and hence the above observation. Super silly.
With Java10+, you could have used an inbuilt capability copyOf
for creating an unmodifiable list, like this:
List<Person> persons = generatePersons();
List<Person> unmodifiableList = List.copyOf(persons);
Also, the current list that you're creating using Collector.collectingAndThen
is actually immutable as mentioned in the documentation as well.
Well in your first case someone has access to List<Person> unmodifiableList
and can edit it, but when you collect
no one has access to that List
generated by Collectors.toList
- so you are good.
What you are probably missing is that Collectors::toList
will create a new List - which should really be obvious; and you wrap it into an unmodifiable one, thus the result of that is truly unmodifiable.
Also in java-10 there is special collector for that:
List<Integer> result = Arrays.asList(1, 2, 3, 4)
.stream()
.collect(Collectors.toUnmodifiableList());
This collector uses List::of
internally - immutable collections added in java-9, thus for example they don't support nulls.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With