Java Stream
Overview
Java 8 引入用于操作集合(Collection)的 Stream API,它将元素集合抽象为流(stream),元素如同水流一样在管道(pipeline)中传输,我们可以方便地对流进行各种操作(Operation),最终得到我们想要的结果,我们将这种操作的方式称为流式处理(stream processing)
操作分类:
- Intermediate operations: 返回一个新的 Stream,可进行链式操作
- Terminal operations: 返回一个 result 或 side-effect,只能放在最后
如下是一个使用 Stream 对 Collection 进行操作的代码示例,其中filter
为中间操作,forEach
为终止操作
Stream 特点:
- Lazy Evaluation: 中间操作不会立即执行,只有在遇到终止操作时流才开始真正的遍历,即一次遍历中执行多个操作(映射,过滤等),这种特性称为惰性求值(lazy evaluation),这种特性使得 Stream API 可以进行更高效的操作
- Internal Iteration: 传统的集合操作是外部迭代(external iteration),即用户需要手动迭代集合中的每一个元素,而 Stream API 是内部迭代(internal iteration),用户只需要告诉 Stream API 需要对集合进行什么操作,而不需要关心具体的迭代过程
- Immutability: Stream 不会改变原有的数据结构,它只是对原有的数据进行操作,并返回一个新的 Stream
- Parallel Processing : JDK 源码注解中提到 Stream pipelines may execute either sequentially or in parallel, 即 Stream 既可被顺序处理,也可并行处理,从而充分利用多核处理器的优势
Methods
Method | 方法作用 | Operation 类别 |
---|---|---|
count | 计数 | terminal |
forEach | 迭代处理 | terminal |
reduce | 归约 | terminal |
collect | 收集 | terminal |
findAny | 查找 | terminal |
anyMatch | 匹配 | terminal |
filter | 过滤 | intermediate |
sorted | 排序 | intermediate |
distinct | 去重 | intermediate |
limit | 取用前几个 | intermediate |
skip | 跳过前几个 | intermediate |
map | 映射 | intermediate |
concat | 拼接 | intermediate |
To perform a computation, stream operations are composed into a stream pipeline. A stream pipeline consists of a source (which might be an array, a collection, a generator function, an I/O channel, etc), zero or more intermediate operations (which transform a stream into another stream, such as filter(Predicate)), and a terminal operation (which produces a result or side-effect, such as count() or forEach(Consumer)). Streams are lazy; computation on the source data is only performed when the terminal operation is initiated, and source elements are consumed only as needed.
创建 Stream
Methods 分析
filter
Stream<T> filter(Predicate<? super T> predicate)
Returns a stream consisting of the elements of this stream that match the given predicate.
filter 方法接受一个 Predicate 函数式接口实例[[functional_interface]],用于过滤流中的元素,返回一个新的 stream,其中包含符合条件的元素
Predicate 是一个 Java 8 新增的函数式接口,它接受一个参数并返回一个布尔值,我们通常使用 Lambda 表达式来创建 Predicate 实例
forEach,find,match
Stream 支持类似于 Collection 的遍历以及查询的操作,需要注意的是,Stream 中的元素是以Optional
类型存在的
Traverse
void forEach(Consumer<? super T> action)
forEach 接受一个 Consumer 函数式接口,用于遍历流中的每一个元素,并对其进行操作
Consumer 是一个 Java 8 新增的函数式接口,它接受一个参数,无返回值,例如System.out::println;
Find
Optional<T> findFirst()
Returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty. If the stream has no encounter order, then any element may be returned.Optional<T> findAny()
Returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty. If the stream has no encounter order, then any element may be returned.
Match
boolean anyMatch(Predicate<? super T> predicate)
只要有一个元素匹配传入的条件,就返回 trueboolean allMatch(Predicate<? super T> predicate)
所有元素都匹配传入的条件,才返回 trueboolean noneMatch(Predicate<? super T> predicate)
所有元素都不匹配传入的条件,才返回 true
map,flatMap
map 意为映射,可将一个 Stream 中的元素映射成另一个 Stream,如下代码将一个 String 类型的 Stream 映射成一个 Integer 类型的 Stream
<R> Stream<R> map(Function<? super T,? extends R> mapper)
Returns a stream consisting of the results of applying the given function to the elements of this stream.<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)map
方法接受一个函数式接口实例mapper,根据 mapper 将流中的元素映射成新的元素,返回一个新的stream,其中包含映射后的元素flatMap
方法接受一个函数式接口实例mapper ,用于将流中的元素映射成流,并将映射后的流扁平化,即将多个流连接成一个流,返回拼接后的 stream
reduce
reduce
意为归约,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。
Optional<T> reduce(BinaryOperator<T> accumulator)
无初始值,返回一个 Optional,参数为一个 BinaryOperator 函数式接口实例,用于将流中的元素两两结合
Performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
Parameters:- accumulator - an associative, non-interfering, stateless function for combining two values
Returns:
an Optional describing the result of the reductionT reduce(T identity, BinaryOperator<T> accumulator)
有初始值,返回类型与初始值的类型一致,参数为初始值和一个 BinaryOperator 函数式接口实例<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
Parameters:
identity
the identity value for the combiner functionaccumulator
an associative, non-interfering, stateless function for incorporating an additional element into a resultcombiner
an associative, non-interfering, stateless function for combining two values, which must be compatible with the accumulator function
Returns:
the result of the reduction
Associative(可结合的):这意味着累积器函数在处理多个值时,其操作的顺序不影响最终结果。即无论值是如何组合的,累积器函数总是产生相同的结果。例如,加法和乘法都是可结合的操作。
Non-interfering(不干扰的):累积器函数在处理值时不会改变这些值的状态。它只是简单地将值组合起来,而不影响原始值。
Stateless(无状态的):累积器函数不依赖于或修改任何外部状态。它只根据传入的参数来计算结果,不涉及任何外部的、可变的或全局的状态。
collect
stream()
方法可以将集合,数组转换为 Stream,而collect()
方法则可以将 Stream 转换为集合
count,max,min
如下方法均为 terminal operation
long count()
Returns the count of elements in this stream.Optional<T> max(Comparator<? super T> comparator)
Returns the maximum element of this stream according to the provided Comparator.Optional<T> min(Comparator<? super T> comparator)
Returns the minimum element of this stream according to the provided Comparator.
Ref
Stream iterate
oracle docs
Java8 新特性之 Stream 流(含具体案例)
由浅入深体验 Stream 流(附带教程)
Java 8 Stream 和 Optional: 实践指南
Reducing a Stream
Java Stream