【问题标题】:Understanding java 8 stream's filter method了解java 8流的过滤方法
【发布时间】:2014-11-01 09:39:33
【问题描述】:

我最近了解了 Java 8 中的 Streams 并看到了这个例子:

IntStream stream = IntStream.range(1, 20);

现在,假设我们要找到第一个可以被 3 和 5 整除的数字。我们可能会 filter 两次和 findFirst 如下:

OptionalInt result = stream.filter(x -> x % 3 == 0)
                               .filter(x -> x % 5 == 0)
                               .findFirst();

这听起来很合理。当我尝试这样做时,令人惊讶的部分出现了:

OptionalInt result = stream.filter(x -> {System.out.println(x); return x % 3 == 0;})
                           .filter(x -> {System.out.println(x); return x % 5 == 0;})
                           .findFirst();

System.out.println(result.getAsInt());

我希望得到类似:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20,然后是:3 6 9 12 15 18。因为我们首先遍历了 1 到 20 之间的所有数字,只过滤掉那些可以被 3 整除的数字,然后迭代这个新的 Stream 并找到那些可以被 5 整除的数字。

但是我得到了这个输出:1 2 3 3 4 5 6 6 7 8 9 9 10 11 12 12 13 14 15 15 15

看起来它并没有遍历所有数字。此外,它似乎只检查x % 5 == 0 中那些可被 3 整除的数字。

我不明白它为什么不遍历所有数字。

这是代码的在线 sn-p:http://www.tryjava8.com/app/snippets/5454a7f2e4b070922a64002b

【问题讨论】:

    标签: java filter java-8 java-stream


    【解决方案1】:

    嗯,关于流需要理解的一点是,与列表不同,它们不(必然)保存所有项目,而是一次计算每个项目(惰性求值)。

    这意味着当您执行IntStream stream = IntStream.range(1, 20); 时,您实际上并没有创建一个包含 20 个项目的集合。您创建了一个动态计算的集合。每次调用此流的next 都会计算下一项。其余的项目仍然“不存在”(有点说)。

    过滤器也是如此。

    当您添加检查除以 3 的过滤器时,您将获得一个由 2 个计算组合而成的新流 - 第一个计算返回从 1 到 20 的数字,第二个计算返回除以的数字3. 重要的是要了解每次只计算第一项。这就是为什么当您添加除以 5 的检查时,它仅适用于可被 3 整除的那些项目。与打印停止在 15 处的原因相同。findFirst 方法返回通过所有 3 次计算的第一个数字( 1-20范围计算,除以3计算,除以5计算)。

    【讨论】:

      【解决方案2】:

      Stream 是一种惰性求值机制,可以有效地处理集合。这意味着除非最终(终端)操作需要,否则不会评估 Stream 上的所有中间操作。

      在您的示例中,终端操作是firstFirst()。这意味着 Stream 将评估中间操作的管道,直到找到将输入 Stream 通过所有中间操作传递的单个 int。

      第二个过滤器只接收通过第一个过滤器的整数,因此它只处理数字 3,6,9,12,15 然后停止,因为 15 通过了过滤器,并提供findFirst() 操作唯一的输出它需要。

      只要终端操作仍然需要数据,第一个过滤器只会处理输入Stream的整数,因此它只会处理1到15。

      【讨论】:

        猜你喜欢
        • 2015-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多