了解java 8流的过滤方法 [英] Understanding java 8 stream's filter method

查看:354
本文介绍了了解java 8流的过滤方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在Java 8中了解了 Stream s,并看到了这个例子:

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

现在假设我们想找到第一个可以被3和5分解的数字。我们可能会过滤两次, findFirst 如下:

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

这听起来很合理。当我尝试这样做时,出人意料的部分来了:

  OptionalInt result = stream.filter(x  - > {System.out (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整除的数字。



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



这是一个在线代码片段: http://www.tryjava8.com/app/snippets/5454a7f2e4b070922a64002b



这意味着当你做了 IntStream stream = IntStream.range(1,20); 实际上创建了20个项目的集合。您创建了一个动态计算的集合。每次调用这个流的 next 将计算下一个项目。其余的项目仍然不存在(有点说)。

过滤器也一样。

当你添加一个被3除法的过滤器时,你会得到一个新的流,它是由2个计算组成的 - 第一个返回从1开始的数字直到达到20,第二个计算返回除以3.重要的是要明白,每次只计算第一项。这就是为什么当你添加除法检查5时,它只能处理那些可以被3整除的项目。同样也是为什么打印在15停止。 findFirst 方法返回第一个通过所有3个计算的数字(1-20范围计算,除以3计算和除以5计算)。

I recently learned about Streams in Java 8 and saw this example:

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

Now, let's say that we want to find the first number that's divisable both by 3 and a 5. We'd probably filter twice and findFirst as follows:

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

That's all sounds pretty reasonable. The surprising part came when I tried to do this:

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());

I expected to get something like: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 and then: 3 6 9 12 15 18. Because we first iterate over all the the numbers between 1 to 20, filter out only those that are divisable by 3 and then iterate this new Stream and find those that are divisable by 5.

But instead I got this output: 1 2 3 3 4 5 6 6 7 8 9 9 10 11 12 12 13 14 15 15 15

It looks like it doesn't go over all the numbers. Moreover, it looks like it checks x % 5 == 0 only for those numbers that are divisable by 3.

I don't understand how come it doesn't iterate over all of the numbers.

Here's an online snippet of the code: http://www.tryjava8.com/app/snippets/5454a7f2e4b070922a64002b

解决方案

Well, the thing to understand about streams is that, unlike lists, they don't (necessarily) hold all the items but rather compute each item at a time (lazy evaluation).

It means that when you did IntStream stream = IntStream.range(1, 20); you didn't actually create a collection with 20 items. You created a dynamically computed collection. Each call to this stream's next will compute the next item. The rest of the items are still "not there" (sort of speaking).

Same goes for the filter.

When you add the filter that's checking division by 3 you'll get a new stream that's combined of 2 computations - the first one returns the numbers from 1 until it gets to 20, the second computation returns the numbers that are divided by 3. It's important to understand that each time only the first item is calculated. That's why when you added the check for division by 5 it only worked on those items that were divisible by 3. Same goes as to why the printing stopped at 15. The findFirst method returns the first number that passes all 3 computations (the 1-20 range computation, the division by 3 computation and the division by 5 computation).

这篇关于了解java 8流的过滤方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆