有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Peek()真的很想看到元素流过管道中的某个点

用最简单的方式表达我的问题:

根据JavaDoc

Peek() method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline.

我有一根10米长的管子,距离3米和7米 从输入头我有两个标记[akapeek()]用于检查/调试我的元素

现在从输入端开始,我给出1,2,3,4,5的输入

在x=4米处,我有一个filter(),它过滤所有小于等于^{的元素

现在,根据Java文档,我应该能够在距离37米的地方看到我在管道中的输入发生了什么

距离3处(.peek())的标记1处的输出应该是1,2,3,4,5不应该是?? 而marker2距离7处的输出显然应该是4,5

但实际情况并非如此,产量在第一市场(.peek())仅1,2,3而在第二市场4,5


我为测试我的理论而执行的代码:

final List<Integer> IntList=
    Stream.of(1, 2, 3, 4, 5)
    .peek(it -> System.out.println("Before Filtering "+it)) // should print 1,2,3,4,5
    .filter(it -> it >= 3)
    .peek(it -> System.out.println("After Filtering: "+it)) //should print 4,5
    .collect(Collectors.toList());

实际产量:

Before Filtering 1
Before Filtering 2
Before Filtering 3
After Filtering: 3
Before Filtering 4
After Filtering: 4
Before Filtering 5
After Filtering: 5

预期的输出(开发人员在阅读JavaDoc后应该怎么想(……主要是为了支持调试,在调试中,您希望看到元素在管道中流过某个点时……)

    Before Filtering 1
    Before Filtering 2
    Before Filtering 3
    Before Filtering 4
    Before Filtering 5
    After Filtering: 4
    After Filtering: 5

如果.peek()不仅仅是为了在管道中的特定点进行调试,那么它的定义是不明确的

很抱歉我讲了一个关于管道的故事,我想这样我就可以最好地解释我想问的问题了


共 (1) 个答案

  1. # 1 楼答案

    不可以。流可能会根据需要进行延迟评估,并且操作顺序没有严格定义,尤其是在peek()操作时。这使得streams API能够支持非常大的流,而不会严重浪费时间和内存,并且允许某些实现简化。特别是,在下一阶段开始之前,无需对管道的单个阶段进行全面评估

    假设根据您的假设,以下代码将是多么浪费:

    IntStream.range(1, 1000000).skip(5).limit(10).forEach(System::println);
    

    这条流从100万个元素开始,到10个元素结束。如果我们充分评估每个阶段,我们的中间值将分别为100万、99995和10个元素

    作为第二个示例,以下流不能一次评估一个阶段(因为IntStream.generate返回一个无限流):

    IntStream.generate(/* some supplier */).limit(10).collect(Collectors.toList());
    

    您的管道确实会通过第一个peek传递每个元素,然后只通过第二个peek传递一个子集。但是,管道会以元素大调而不是阶段大调顺序执行此求值:它会对管道求值1,然后将其放到过滤器处,然后再求值2。一旦对管道求值3,它就会通过过滤器,从而执行peek语句,然后对4和5执行相同的操作