问题 Java 8 Stream是安全返回类型吗?


Java 8 Streams是公共方法的安全返回类型,因为在给定流的基础对象的情况下,它是不可能的吗?

例如,如果我有 List 和 return list.stream(); 可以以任何方式使用返回值来改变原始列表吗?

从API来看,我认为这不可能,但我想确认一下。


11968
2018-04-14 21:29


起源

阅读以下内容,您将了解为什么流不会修改源(示例中的集合)的好概念: oracle.com/technetwork/articles/java/... - alfasin
从列表中获取流不应该修改数据结构“本身”,但如果它包含可变对象,它可以修改其内容。但是这个原则无论如何都是关于数据结构的。 - Alexis C.


答案:


是的,这样做是安全的。流不会/不应该修改基础数据结构。

一些摘录自 java.util.stream.Stream

一个 序列 元素[...]。

收藏和流虽然有一些肤浅的相似之处,但却有不同的目标。馆藏主要关注其元素的有效管理和访问。相比之下, 流不提供直接访问或操纵其元素的方法 [...]。

为了保持正确的行为,[流操作的行为参数...]必须是非干扰的(它们不会修改流源)。

来自 java.util.stream 描述

Streams在几个方面与集合不同:

  • 没有存储空间 流不是存储元素的数据结构;相反,它通过计算操作管道传递来自源[...]的元素。
  • 功能性。 对流的操作会产生结果,但不会修改其源。

你可能也看到了 不干涉


[…] 这将是 不可能 从给定流的基础上改变底层对象。

虽然它会 可能 写我们的 拥有 实施 java.util.Stream 修改了底层数据结构,这样做是错误的。 ; )


回应@AlexisC的评论:

从列表[...]获取流可以修改它 内容 如果它包含可变对象。

这是一个公平的观点。如果我们有一个流 可变的元素, 我们可以做的:

myObj.stream().forEach(( Foo foo ) -> ( foo.bar = baz ));

13
2018-04-14 21:35



除了反思当然。我没有尝试过,但如果你不能使用反射来访问和修改流的底层结构,我会非常惊讶。 - kajacx
只是为了澄清,集合本身不能被流修改,但是如果它们是可变的则可以是项目。如果您不希望修改项目本身,请通过final和encapsulation使它们不可变。 - tmn
@kajacx有可能通过反射获得对底层数据结构的引用,但对于Java中的任何不变性都可以这样说。如果你想写一些hacky代码,没有什么是不可变的。同样适用于例如 Collections.unmodifiableList。 - Radiodef
Stream vs. List的另一个方面是实际创建其元素的时间点。由于流被懒惰地执行,调用者隐式地决定何时发生。根据调用者处理Stream的时间,结果可能不同。 (如果元素可以随时间变化)而List表示a 快照 调用时返回的方法。 - Rüdiger Herrmann