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

时间:2018-07-28 13:37:23

标签: java java-8 java-stream short-circuiting

我正在阅读有关Java流的短路操作的信息,并且在某些文章中发现command = input("What would you like to do? Read or add? >> ") programactive = True if command == "Read" or command == "read": directory = open('directory.txt', 'r') contents = directory.read() print(contents) directory.close() elif command == "Add" or command == "add": while programactive == True: directory = open('directory.txt', 'a') new_name = input("Add a new name to the list. >> ") new_email = input("Add a new email for that name. >> ") combined = "\n" + new_name + ", " + new_email directory.write(combined) cont = input("Add more? Yes or No >> ") if cont == "No" or cont == "no": directory.close() programactive = False 是短路操作。

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

现在我很困惑; skip()是否短路?

2 个答案:

答案 0 :(得分:17)

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堆空间”的内容。

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

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

答案 1 :(得分:6)

只想在这里加两分钱,这个关于使流短路的想法一般是无限复杂的(至少对我来说,至少在某种意义上说,我必须从头开始通常两次)。我将在答案的结尾处转到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,其中明确指出:

  

这是一个短路的有状态中间操作