阿Stream当存在将仅被遍历终端操作,如count(),collect()或forEach()。否则,Stream将不会执行任何操作。
在以下示例中,没有终端操作添加到Stream,因此该filter()操作将不会被调用,并且不会产生任何输出,因为peek()它不是终端操作。
IntStream.range(1, 10).filter(a -> a % 2 == 0).peek(System.out::println);
住在伊迪欧
这是Stream具有有效终端操作的序列,因此产生输出。
您也可以使用forEach代替peek:
IntStream.range(1, 10).filter(a -> a % 2 == 0).forEach(System.out::println);
住在伊迪欧
输出:
2
4
6
8
执行终端操作后,将Stream消耗这些资源,并且无法重复使用。
尽管给定的流对象无法重用,但是创建Iterable委托给流管道的可重用的对象很容易。这对于返回实时数据集的修改视图而不必将结果收集到临时结构中很有用。
List<String> list = Arrays.asList("FOO", "BAR"); Iterable<String> iterable = () -> list.stream().map(String::toLowerCase).iterator(); for (String str : iterable) { System.out.println(str); } for (String str : iterable) { System.out.println(str); }
输出:
foo
bar
foo
bar
这是有效的,因为Iterable声明了一个抽象方法。这有效地使其成为一个功能接口,由lambda实现,该lambda在每个调用上创建一个新流。Iterator<T> iterator()
通常,a的Stream操作如下图所示:
注意:即使没有终端操作,也会始终执行参数检查:
try { IntStream.range(1, 10).filter(null); } catch (NullPointerException e) { System.out.println("We got a NullPointerException as null was passed as an argument to filter()"); }
住在伊迪欧
输出:
我们得到了一个NullPointerException,因为null被作为参数传递给 filter()