peek()和allMatch()如何在Java 8流API中协同工作

peek()和allMatch()如何在Java 8流API中协同工作,java,java-8,java-stream,Java,Java 8,Java Stream,我发现了一个关于peek方法的Java8流API的测验,如下所示 Arrays.asList("Fred", "Jim", "Sheila") .stream() .peek(System.out::println) .allMatch(s -> s.startsWith("F")); 输出是 Fred Jim 我不知道这条小溪是怎么运作的?我的预期结果应该是 Fred Jim Sheila peek()方法是一个中间操作,它处理流中的每个元素。谁

我发现了一个关于peek方法的Java8流API的测验,如下所示

Arrays.asList("Fred", "Jim", "Sheila")
      .stream()
      .peek(System.out::println)
      .allMatch(s -> s.startsWith("F"));
输出是

Fred
Jim
我不知道这条小溪是怎么运作的?我的预期结果应该是

Fred
Jim
Sheila
peek()方法是一个中间操作,它处理流中的每个元素。谁能给我解释一下。

对于
peek
方法来说(我的重点):

返回一个由该流的元素组成的流,在从结果流中消耗元素时,对每个元素执行提供的操作

因此在本例中,
peek
没有看到
“Sheila”
,因为该值不是从流中消耗的。一旦使用了
“Jim”
,就知道
.allMatch(s->s.startsWith(“F”))
的结果是
false
,因此不需要再使用流中的任何元素

Arrays.asList("Fred", "Jim", "Sheila")
      .stream()
      .peek(System.out::println)
      .allMatch(s -> s.startsWith("F"));
  • 第一次通过时,
    Fred
    被打印出来。这很相配
  • 第二次通过时,
    Jim
    被打印。它不匹配,所以所有匹配 终止,因为“所有不匹配”
  • 因此,最后一项不是从流中消耗的

    • 这是一种称为短路的流优化。本质上,所发生的是
      allMatch
      防止在流上执行不必要的中间操作,因为在最终结果已知时执行这些操作没有意义

      就好像发生了这样的事情:

      take"Fred"
      peek("Fred")
      evaluate("Fred".startsWith("F"))
      decide whether the result of allMatch() is known for sure: Not yet
      
      take"Jim"
      peek("Jim")
      evaluate("Jim".startsWith("F"))
      decide whether the result of allMatch() is known for sure: Yes
      
      当计算
      “Jim”.startsWith(“F”)
      时,
      allMatch(s->s.startsWith(“F”)
      的结果肯定是已知的。无论管道中在
      “Jim”
      之后出现什么值,我们都知道所有以“F”开头的值都是false

      这并不特定于
      peek
      /
      allMatch
      组合,存在多个中间和终端短路操作。声明:

      此外,一些操作被视为短路操作。中间操作是短路,当输入无限大时,可能会产生有限的流。如果终端操作在无限输入时可能在有限时间内终止,则终端操作为短路。在管道中进行短路操作是无限流处理在有限时间内正常终止的必要条件,但不是充分条件


      将其扩展到有限流,短路操作可以避免执行不必要的管道步骤,就像您的示例一样。

      根据allMatch()的Java文档:

      返回此流的所有元素是否与提供的谓词匹配。 如果不需要,则不能对所有元素求值谓词 确定结果。如果流为空,则{@code true}为空 返回,并且未计算谓词

      @阿皮诺特

      该方法评估了产品的通用量化 流元素上的谓词(对于所有xp(x))。如果 流为空,则称量化为空 满足并且总是{@code true}(与P(x)无关)

      要应用于此流元素的谓词 @如果流的所有元素都与 提供的谓词或流为空,否则{@code false}

      就你而言:

      1-

      2-

      不会进行进一步的计算,因为xp(X)=false

      输出为:

      Fred
      Finda
      Fish
      Result true
      
      这里流被完全处理,因为每个元素的xP(x)=true

      p(x) : s -> s.startsWith("F")
      
      X : "Jim"
      
      result : X P(X) = false
      
      boolean result = Arrays.asList("Fred", "Finda", "Fish")
                  .stream()
                  .peek(System.out::println)
                  .allMatch(s -> s.startsWith("F"));
          System.out.println("Result "+result);
      
      Fred
      Finda
      Fish
      Result true