无限流和过滤器

时间:2014-08-06 17:57:08

标签: lambda java-8 java-stream

我是Java 8 Stream API的新手,实际上我并不理解为什么我的代码不起作用:

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = Stream.iterate(0, x -> x+3)
                                        .filter(x -> x>10 && x<100).peek(System.out::println)
                                        .collect(Collectors.toList());
        numbers.forEach(System.out::println);
    }
}

据我了解&#34;懒惰&#34;我写的溪流:

  1. 使用可被3整除的数字创建流

  2. 过滤它并给我一个范围(10,100)的数字流

  3. 将此流收集到列表中

  4. 正如我所看到的,无限循环存在一些问题,所以peek()打印范围(12,99)中的数字,这是好的,但之后再次打印(11,98)等数字。 你能解释一下我犯了什么错吗?

1 个答案:

答案 0 :(得分:3)

编译器和运行时都不知道filter会过滤掉超过100的所有数字。因此,运行时继续生成无限整数并对它们应用过滤器。

您有多种方法可以解决此问题:

使用limit将无限流截断为有限流。这使得以下过滤器有点不必要(如果设置了严格的限制,只有x> 10测试仍然相关)。

public static void main(String[] args) {
    List<Integer> numbers = Stream.iterate(0, x -> x+3)
                                    .limit(34)
                                    .filter(x -> x>10 && x<100).peek(System.out::println)
                                    .collect(Collectors.toList());
    numbers.forEach(System.out::println);
}

使用IntStream.range并乘以3:

public static void main(String[] args) {
    List<Integer> numbers = IntStream.range(0, 34)
                                    .map(x -> 3*x)
                                    .collect(Collectors.toList());
    numbers.forEach(System.out::println);
}

一般来说,&#34;懒惰&#34; Streams意味着它们只在遇到终端(最终)操作时才开始执行。如果操作需要处理列表中的所有元素(例如toList),则不应该将其传递给无限流。

当您处理无限流时,您的选项要么将其截断为有限流(使用限制),要么使终端操作不必处理流的所有元素(示例:anyMatch ,findFirst,findAny)。