我是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;我写的溪流:
使用可被3整除的数字创建流
过滤它并给我一个范围(10,100)的数字流
将此流收集到列表中
正如我所看到的,无限循环存在一些问题,所以peek()打印范围(12,99)中的数字,这是好的,但之后再次打印(11,98)等数字。 你能解释一下我犯了什么错吗?
答案 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)。