skip() 方法是短路操作吗?

Is the skip() method a short circuiting-operation?

我正在阅读有关 Java 流的短路操作,并在一些文章中发现 skip() 是一种短路操作。

在另一篇文章中他们没有提到 skip() 作为短路操作。

现在我很困惑; skip()是不是短路操作?

From the java doc under the "Stream operations and pipelines" section :

An intermediate operation is short-circuiting if, when presented with infinite input, it may produce a finite stream as a result. A terminal operation is short-circuiting if, when presented with infinite input, it may terminate in finite time.

强调我的。

如果您要在无限输入上调用 skip,它不会产生有限流,因此不是短路操作。

JDK8 中唯一的短路中间操作是 limit,因为它允许在有限时间内完成无限流的计算。

示例:

如果您要使用 skip 执行此程序:

String[] skip = Stream.generate(() -> "test") // returns an infinite stream
                      .skip(20) 
                      .toArray(String[]::new);

它不会产生 finite 流,因此你最终会得到类似于 "java.lang.OutOfMemoryError: Java heap space".

的东西

而如果您使用 limit 执行此程序,它将导致计算在 finite 时间内完成:

String[] limit = Stream.generate(() -> "test") // returns an infinite stream
                       .limit(20)
                       .toArray(String[]::new);

只是想在这里加上我的两分钱,这个想法一般来说 短路流是无限复杂的(至少对我来说,至少在某种意义上我通常不得不挠头两次)。顺便说一句,我会在答案的末尾到达 skip

我们以此为例:

Stream.generate(() -> Integer.MAX_VALUE);

这是一个无限的流,我们都同意这一点。让我们通过记录为这样的操作将其短路(不同于skip):

Stream.generate(() -> Integer.MAX_VALUE).anyMatch(x -> true);

效果很好,添加一个 filter:

怎么样?
Stream.generate(() -> Integer.MAX_VALUE)
      .filter(x -> x < 100) // well sort of useless...
      .anyMatch(x -> true);

这里会发生什么?好吧,这永远不会结束,即使有像 anyMatch 这样的短路操作——但它永远不会真正短路任何东西。

另一方面,filter不是短路操作,但您可以这样设置(仅作为示例):

someList.stream()
        .filter(x -> {
           if(x > 3) throw AssertionError("Just because");            
})

是的,它很丑,但它短路了...这就是我们(强调我们,因为 很多 的人,不同意)实施 short-circuiting reduce -抛出没有堆栈跟踪的异常。

java-9 中添加了另一个短路的中间操作:takeWhile 其行为有点像 limit 但针对特定条件。

公平地说,关于 skip 的大部分答案已经由 Aomine 给出,但最简单的答案是 它没有记录在案.通常(在某些情况下会更正文档),但这是您应该查看的首要指示。请参阅 limittakeWhile 示例,其中明确表示:

This is a short-circuiting stateful intermediate operation