gpt4 book ai didi

java - 使用 Stream.sum() 多次消费流

转载 作者:行者123 更新时间:2023-12-01 11:42:45 25 4
gpt4 key购买 nike

A stream should be operated on (invoking an intermediate or terminal stream operation) only once.



我明白了,但是为什么找到流的总和不消耗它呢?我可以运行下面的代码,没有任何异常(exception)。
double totalPrice = stream.mapToDouble(product -> product.price).sum();
List<Product> products = stream.map(this::convert).collect(Collectors.toList());

为什么 sum不是终端运营商吗?它与将流元素收集到列表中有何不同?

最佳答案

文档

没有指定流是否可以被消费一次或多次。文档说“应该操作......只操作一次”,而不是“必须”或“可以”。

取决于 关于流的底层实现和来源。因此,多次执行它的能力是未定义 一般用于流。

实现

您可能能够找到可以使用两次或多次的流,特别是对于自定义实现或预防检测可能过于昂贵而无法实现的实现。

但同样,文档不支持它。它可能是当前的实现,但这可以随时在任何 Java 版本中更改。它可能会抛出异常,可能会导致错误行为,但未指定。

这是一个使用 sum() 的小例子引发异常,因为它具有这样的检测(JDK 11):

Stream<Integer> stream = List.of(1, 2, 3, 4).stream();

int first = stream
.mapToInt(i -> i)
.sum();

int second = stream
.mapToInt(i -> i)
.sum();

// throws IllegalStateException: stream has already been operated upon or closed

结论

意图肯定是 不要多次使用流 ,正如文档所暗示的那样。因此,即使某个实现有可能, 避免它 .

为什么?

你可能会问自己为什么 Stream不支持多次迭代。毕竟,像 ArrayList 这样的集合对此没有问题,这似乎是一个常见的用例。

流有很多 更大范围比 Collection 。在典型集合上创建的流可能很容易支持多次迭代。但是与文件或网络连接等资源相关联的流,例如 Files.lines(...) 返回的流不能。这样的功能对于文件来说将是非常耗费资源和昂贵的,甚至可能不支持其他功能,例如之后可能会关闭的 Web 连接。

更进一步,您可以轻松创建一个无限流来生成随机数:
Stream<Double> stream = Stream.generate(Math::random);

虽然它可以很容易地支持多种用法,但再次迭代时不可能再次生成相同的序列。

另一个例子,一个消耗资源而不恢复资源的流:
Queue<Integer> queue = ...
Stream<Integer> stream = Stream.generate(queue::poll);

此流将从队列中删除元素。它们在流使用后消失了。流的另一次迭代将不再能够处理死对象。

关于java - 使用 Stream.sum() 多次消费流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61280342/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com