【发布时间】:2019-01-05 09:39:19
【问题描述】:
我在阅读 Java 流的短路操作,在一些文章中发现 skip() 是一种短路操作。
在另一篇文章中,他们没有提到 skip() 是一种短路操作。
现在我很困惑; skip() 是不是短路操作?
【问题讨论】:
标签: java java-8 java-stream short-circuiting
我在阅读 Java 流的短路操作,在一些文章中发现 skip() 是一种短路操作。
在另一篇文章中,他们没有提到 skip() 是一种短路操作。
现在我很困惑; skip() 是不是短路操作?
【问题讨论】:
标签: java java-8 java-stream short-circuiting
From the java doc under the "Stream operations and pipelines" section :
一个 中间操作是短路的,如果,当出现 无限输入,因此可能会产生有限流。一个终端 如果出现无限输入,则操作是短路的, 它可能会在有限的时间内终止。
强调我的。
如果您要在无限输入上调用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);
【讨论】:
limit,这里还有一个:stackoverflow.com/a/51575391/1059372
limit 是 jdk8 中唯一的一个,这就是问题的标记。我想我会通过在答案中说明这一点来更清楚地说明这一点。
只想在这里加上我的两分钱,一般这种短路流的想法是无限复杂的(至少对我来说,至少在我必须从头开始的意义上通常头两次)。顺便说一句,我会在答案的末尾找到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 给出的,但最简单的答案是 没有这样记录。通常(在某些情况下文档会被更正),但这是您应该查看的第一个指示。例如,请参阅limit 和takeWhile,其中明确表示:
这是一个短路状态的中间操作
【讨论】: