了解java Stream.limit()操作

了解java Stream.limit()操作,java,functional-programming,java-stream,Java,Functional Programming,Java Stream,我在学习说: 返回由此流的元素组成的流,该流被截断为长度不超过maxSize 这可以从以下方面理解: Stream.of(1,2,3,4,5,6,7,8) .limit(3) .forEach(i -> { System.out.print(i + ","); }); //prints: 1,2,3, 但是,当与其他流方法一起使用时,它具有批处理元素的效果: Stream.of(1,2,3,4,5,6,7) .filter(i ->

我在学习说:

返回由此流的元素组成的流,该流被截断为长度不超过maxSize

这可以从以下方面理解:

Stream.of(1,2,3,4,5,6,7,8)
    .limit(3)
    .forEach(i -> {
        System.out.print(i + ",");
    });  //prints: 1,2,3,
但是,当与其他流方法一起使用时,它具有批处理元素的效果:

Stream.of(1,2,3,4,5,6,7)
    .filter(i -> {
        System.out.println("Filtering "  + i + ": " + (i%2 == 0));
        return i%2 == 0;
    })
    .map(i-> {
        System.out.println("Mapping " + i + " to " + i*i);
        return i*i;
    })
    .limit(2)
    .forEach(i -> System.out.println("---> " + i));
印刷品:

Filtering 1: false
Filtering 2: true
Mapping 2 to 4
---> 4
Filtering 3: false
Filtering 4: true
Mapping 4 to 16
---> 16
在这里,您可以看到元素是按2批处理的

我有以下疑问:

  • 为什么它不只处理前两个元素1和2?也就是说,为什么输出不只是:

     Filtering 1: false
     Filtering 2: true
     Mapping 2 to 4
     ---> 4
    
  • 为什么它没有处理最后四个元素5、6、7和8并打印以下内容

     Filtering 5: false
     Filtering 6: true
     Mapping 6 to 36
     ---> 36
     Filtering 7: false
     Filtering 8: true
     Mapping 8 to 64
     ---> 64
    
  • 处理
    1
    2
    1
    是奇数,因此
    过滤器将其从流管道中删除
    2
    是偶数,并通过整个流管道,导致
    4
    forEach
    中打印出来

  • 溪流在性质上是懒惰的。由于使用了
    limit(2)
    只有两个元素可以通过
    limit
    管道步骤
    2
    4
    通过整个流管道,导致
    4
    16
    forEach
    中打印出来

  • limit()
    是一种短路状态的中间操作,如下所示:

    诸如limit(n)或findFirst()之类的短路操作可以使无限流上的计算在有限时间内完成

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


    它们不是两批一批地处理的。它们一个接一个地被处理,但是由于第一个和第三个被过滤器拒绝,它们没有被映射,也就是说,它们没有被传递到管道的下一个操作,即映射函数。这取决于限制指令的位置。@eric.v like?还有其他例子吗?我建议阅读,然后想象你在管道中插入一个“最多让n个元素通过”阶段,一次在开始,一次在结束…为什么6和8没有通过限制?事实上,5、6、7和8似乎都没有经过
    filter()
    (例如,输出中没有
    Filtering 5:false
    ),对吗?还是我遗漏了什么?@anlr,因为
    limit()
    是一种短路操作,不完全理解短路的含义,需要在线阅读更多内容。但一个简单的问题是,这是否意味着它会在任意时间后终止管道执行?@anir是的。短路的一个例子是
    &&
    操作员。在
    (a==1&&b==1)
    中,如果左条件为false,则不计算右条件。@anir,Java流API以“拉方式”工作,而不是“推方式”。这意味着它首先评估最后一个操作,然后评估链中最后一个操作。因为这是“拉动方式”,所以没有任何方式可以“拉动”比“限制”阶段定义的元素更多的元素。