Creating an immutable list from an existing list using streams

泪湿孤枕 提交于 2020-06-08 07:08:49

问题


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 unmodifiablePersonsand 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.


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/53013435/creating-an-immutable-list-from-an-existing-list-using-streams

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!