Java 8 引入,位于java.util.stream
包中,与 java.io 包里的输入输出流 InputStream 和 OutputStream 是不同的概念。
Stream API 借助 Lambda 表达式,可以提高编程效率和程序可读性。
Stream的特性:
- 元素序列:流提供了一个特定类型元素的集合,不存储元素,只获取和计算元素
- 源:Collection/Arrays(
Arrays.stream(Object[])
)/ I/O channel等 - 聚合操作:filter, map, limit, reduce, find, match等
- 管道:中间操作返回流本身,多个操作可以组成流水线
- 自动迭代:内部对源进行自动的迭代
流的操作类型分为两种,组成一个流管道
- Intermediate:流可以后面跟有零个或多个中间操作
- Terminal:流只能有一个终结操作,位于最后,例如
Stream.forEach / IntStream.sum
等,产生一个最终结果,或者一个副作用(side effect)
提供串行( Collection.stream()
)和并行(Collection.stream()
)两种模式进行操作
Intermediate操作都是 lazy 的,多个操作只会在 Terminal 操作的时候融合起来执行,一次循环完成
操作一个无限大的 Stream,而又希望在有限时间内完成操作,需要进行短路(short-circuiting)操作,比如limit()
Stream生成
- 集合: Collection接口中的
stream() / parallelStream()
方法 - 数组:
Arrays.stream(Object[])
; - 静态方法 :
Stream.of(Object[]), IntStream.range(int, int),Stream.iterate(Object, UnaryOperator)
- 文件:
BufferedReader.lines()
- 随机数:
Random.ints()
- 其他:
BitSet.stream(), Pattern.splitAsStream(java.lang.CharSequence), JarFile.stream()
常用的方法StreamSupport.stream(Spliterator<T> spliterator, boolean parallel)
,其中Spliterator<T>
接口的含义如下:
- 遍历:遍历单个元素
tryAdvance()
,也可以批量遍历forEachRemaining()
-
characteristics()
:返回分割器和数据元素的属性,所有可能的属性有ORDERED, DISTINCT, SORTED, SIZED, NONNULL, IMMUTABLE, CONCURRENT, and SUBSIZED
,这些属性可以用来控制,专门化或简化计算 -
estimateSize()
:剩余元素数量的估计值 -
trySplit()
:数据分割,返回一个新的Spliterator迭代器,分出一半待遍历的元素由新的Spilterator遍历 - 不是线程安全的,并行算法应该确保单个Spliterator一次只被一个线程使用
具体实现有ArrayListSpliterator
,IteratorSpliterator<T>
等,底层还是数组和Iterator
,例如ArrayListSpliterator
的构造函数
ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
int expectedModCount) {
this.list = list; // 要遍历的ArrayList
this.index = origin; // 当前索引
this.fence = fence; // 结束位置,比最后一个元素索引大1
this.expectedModCount = expectedModCount; //确保没有发生修改,对应于modCount变量
}
中间操作
操作 | 描述 |
---|---|
Stream<T> filter(Predicate<? super T> predicate) |
过滤元素,返回过滤后的元素 |
<R> Stream<R> map(Function<? super T, ? extends R> mapper) |
对每个元素执行给定的函数,从而变成一个新的集合 |
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) |
flatMap 扁平映射,流中的每个元素转换为一个新的流,最终合并为一个新的流 |
Stream<T> distinct() |
去重复,根据equals()
|
Stream<T> sorted(Comparator<? super T> comparator) |
排序 |
Stream<T> peek(Consumer<? super T> action) |
主要用来调试,查看流过的元素 |
Stream<T> limit(long maxSize) |
最长截取前边maxSize个元素 |
Stream<T> skip(long n) |
跳过前n个 |
终结操作
操作 | 描述 |
---|---|
void forEach(Consumer<? super T> action) |
每一个元素都执行相应的表达式 |
Object[] toArray() |
使用流的元素创建一个数组 |
T reduce(T identity, BinaryOperator<T> accumulator) |
元素聚合为一个汇总值 |
<R,A> R collect(Collector<? super T,A,R> collector) |
将流的元素聚合到一个容器中 |
Optional<T> min(Comparator<? super T> comparator) |
返回最小值 |
Optional<T> max(Comparator<? super T> comparator); |
返回最大值 |
long count() |
数目 |
boolean {any,all,none}Match(Predicate<? super T> predicate) |
返回流是否任何/所有/没有的元素与提供的预期相匹配。 |
Optional<T> findFirst() |
返回流的第一个元素(如果有) |
Optional<T> findAny() |
返回流的任何元素(如果有) |