【问题标题】:Creating an immutable list from an existing list using streams使用流从现有列表创建不可变列表
【发布时间】:2019-03-31 11:48:46
【问题描述】:

有一个Person 对象列表。

List<Person> persons = generatePersons();

一个不可修改的列表是用它创建的。

List<Person> unmodifiableList = Collections.unmodifiableList(persons);

我了解unmodifiableList 不支持添加/删除/设置操作。同时它不是不可变的,因为它引用了现有的可修改列表persons,并且每当对persons 列表进行更改时,这些更改也会反映在unmodifiableList 中。

通过这种方式创建了一个不可变列表。

List<Person> immutableList = Collections.unmodifiableList(new ArrayList<>(persons));

这将创建一个不可变列表,因为正在使用转换构造函数。不能对 immutableList 执行添加/删除/设置操作,原始列表 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 对象,因此上述观察结果。超级傻。

【问题讨论】:

  • 你的例子一个不可变的列表。事实上,这是文档给出的示例:docs.oracle.com/javase/8/docs/api/java/util/stream/…
  • @Zircon 我已经用我的观察更新了我的问题。请仔细查看。
  • @Sara 你不是 - 这确实是 Listview
  • 建议通过 JDK 邮件列表中的 this discussion,同时实现 copy 方法与收集器一起收集以设置、列出和映射。
  • @Zircon 已更新编辑 2。

标签: java collections java-8 java-stream collectors


【解决方案1】:

在你的第一种情况下,某人可以访问List&lt;Person&gt; unmodifiableList并且可以编辑它,但是当你collect时,没有人可以访问Collectors.toList生成的List - 所以你很好。

您可能缺少的是 Collectors::toList 将创建一个 new 列表 - 这应该很明显;然后你把它包装成一个不可修改的,因此结果是真正不可修改的。

在 java-10 中也有专门的收集器:

List<Integer> result = Arrays.asList(1, 2, 3, 4)
        .stream()
        .collect(Collectors.toUnmodifiableList());

这个收集器在内部使用List::of - java-9 中添加的不可变集合,因此例如它们不支持空值。

【讨论】:

  • 我很失望他们没有消除 toList() 的可变性歧义。不可变列表和可能不可变列表之间没有太大的实际区别。
  • @shmosel 你的意思是来自Collectors::toList的文档?
  • @shmosel 删除它可能意味着他们必须坚持可变或不可变,我猜。有来自 Stuart Marks 的 cmets,他们认为 Collectors::toList 将在未来返回一个不可变的列表
  • 对,但既然有toUnmodifiableList(),那就没有意义了。
  • @shmosel 对,现在我想知道为什么不明确指定 toList 可修改的 - 好吧,你不能,因为文档是 在那里 已经。让我想起了Optional::getOptional::orElseThrow(没有参数)
【解决方案2】:

使用 Java10+,您可以使用内置功能 copyOf 来创建不可修改的列表,如下所示:

List<Person> persons = generatePersons();       
List<Person> unmodifiableList = List.copyOf(persons);

此外,您使用Collector.collectingAndThen 创建的当前列表实际上也是不可变,如文档中所述。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 2021-07-10
    相关资源
    最近更新 更多