Stream流
Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象。这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选,排序,聚合等。Stream有以下特性及优点:
- 无存储。Stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
- 为函数式编程而生。对Stream的任何修改都不会修改背后的数据源,比如对Stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新Stream。
- 惰式执行。Stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
- 可消费性。Stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
对于流的处理,主要有三种关键性操作:
- 流的创建
- 中间操作(intermediate operation)
- 最终操作(terminal operation)
Stream类关系
从源码的角度来看,Stream接口继承于BaseStream接口。可以看到接口的签名:
public interface Stream<T> extends BaseStream<T, Stream<T>>
而如果结合BaseStream的签名:
public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable
可以分析出这些泛型的作用:T是指定了流中元素数据类型,而S则表明了流的具体类型必然为BaseStream的子类。
而可以看到,BaseStream继承了AutoCloseable,这个类可以百度一下,可以自动关闭资源,所以在进行流操作的时候,不像IO操作那样需要手动调用close()
方法。
而BaseStream有比较重要的一些子类,Stream是其中一个,还有IntStream、DoubleStream等。因为例如Stream<Integer>
这样的写法还是很多的,而自动拆/装箱着实影响了效率,所以才额外准备了这些特殊的Stream类。
流的创建
通过已有的集合来创建流
在Java 8中,除了增加了很多Stream相关的类以外,还对集合类自身做了增强,在其中增加了stream方法,可以将一个集合类转换成流。例如:
Stream<Integer> stream = list.stream();
通过Stream创建流
可以使用Stream类提供的方法,直接返回一个由指定元素组成的流。例如of()
方法:
Stream<Integer> stream = Stream.of