使用流从现有列表创建不可变列表
Creating an immutable list from an existing list using streams
有 Person
个对象的列表。
List<Person> persons = generatePersons();
用它创建了一个不可修改的列表。
List<Person> unmodifiableList = Collections.unmodifiableList(persons);
我了解 unmodifiableList
不支持 add/remove/set 操作。同时它不是不可变的,因为它引用了现有的可修改列表 persons
并且每当对 persons
列表进行更改时,更改也会反映在 unmodifiableList
中。
不可变列表就是这样创建的。
List<Person> immutableList = Collections.unmodifiableList(new ArrayList<>(persons));
这将创建一个不可变列表,因为正在使用转换构造函数。不能对 immutableList
执行 add/remove/set 操作,原始列表 persons
中的任何更改也不会反映在 immutableList
中。
让我们假设 Person
对象也是不可变的。
现在,我想使用流创建这两个列表。
第一个,我创建使用:
List<Person> unmodifiablePersons = persons.stream()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
我迷失了通过流创建 immutableList 的等价物。
我该怎么做?
编辑:
我向原始列表 persons
添加了一个新的 Person
对象并打印了 persons
列表和 unmodifiablePersons
的大小。两者都给我相同的尺寸。
因此,更改会反映到 unmodifiablePersons
,因此它还不是不可变的。我在这里遗漏了什么吗?
编辑 2
傻。应该通过文档。 unmodifiablePersons
确实是一个不可变列表。此外,在创建 unmodifiablePersons
之前添加了新的 Person
对象,因此出现了上述观察结果。超级傻。
在你的第一种情况下 有人 可以访问 List<Person> unmodifiableList
并且可以编辑它,但是当你 collect
没有人可以访问那个 List
由 Collectors.toList
生成 - 所以你很好。
您可能遗漏的是 Collectors::toList
将创建一个 new 列表 - 这应该是显而易见的;然后你把它包装成一个不可修改的,因此它的结果是真正不可修改的。
在 java-10 中还有专门的收集器:
List<Integer> result = Arrays.asList(1, 2, 3, 4)
.stream()
.collect(Collectors.toUnmodifiableList());
此收集器在内部使用 List::of
- 在 java-9 中添加了不可变集合,因此例如它们不支持空值。
使用 Java10+,您可以使用内置功能 copyOf
来创建不可修改的列表,如下所示:
List<Person> persons = generatePersons();
List<Person> unmodifiableList = List.copyOf(persons);
此外,您使用 Collector.collectingAndThen
创建的当前列表实际上也是 不可变的,正如文档中提到的那样。
有 Person
个对象的列表。
List<Person> persons = generatePersons();
用它创建了一个不可修改的列表。
List<Person> unmodifiableList = Collections.unmodifiableList(persons);
我了解 unmodifiableList
不支持 add/remove/set 操作。同时它不是不可变的,因为它引用了现有的可修改列表 persons
并且每当对 persons
列表进行更改时,更改也会反映在 unmodifiableList
中。
不可变列表就是这样创建的。
List<Person> immutableList = Collections.unmodifiableList(new ArrayList<>(persons));
这将创建一个不可变列表,因为正在使用转换构造函数。不能对 immutableList
执行 add/remove/set 操作,原始列表 persons
中的任何更改也不会反映在 immutableList
中。
让我们假设 Person
对象也是不可变的。
现在,我想使用流创建这两个列表。
第一个,我创建使用:
List<Person> unmodifiablePersons = persons.stream()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
我迷失了通过流创建 immutableList 的等价物。
我该怎么做?
编辑:
我向原始列表 persons
添加了一个新的 Person
对象并打印了 persons
列表和 unmodifiablePersons
的大小。两者都给我相同的尺寸。
因此,更改会反映到 unmodifiablePersons
,因此它还不是不可变的。我在这里遗漏了什么吗?
编辑 2
傻。应该通过文档。 unmodifiablePersons
确实是一个不可变列表。此外,在创建 unmodifiablePersons
之前添加了新的 Person
对象,因此出现了上述观察结果。超级傻。
在你的第一种情况下 有人 可以访问 List<Person> unmodifiableList
并且可以编辑它,但是当你 collect
没有人可以访问那个 List
由 Collectors.toList
生成 - 所以你很好。
您可能遗漏的是 Collectors::toList
将创建一个 new 列表 - 这应该是显而易见的;然后你把它包装成一个不可修改的,因此它的结果是真正不可修改的。
在 java-10 中还有专门的收集器:
List<Integer> result = Arrays.asList(1, 2, 3, 4)
.stream()
.collect(Collectors.toUnmodifiableList());
此收集器在内部使用 List::of
- 在 java-9 中添加了不可变集合,因此例如它们不支持空值。
使用 Java10+,您可以使用内置功能 copyOf
来创建不可修改的列表,如下所示:
List<Person> persons = generatePersons();
List<Person> unmodifiableList = List.copyOf(persons);
此外,您使用 Collector.collectingAndThen
创建的当前列表实际上也是 不可变的,正如文档中提到的那样。