1、从迭代到流的操作
流提供了一种让我们可以在此集合更高的概念级别上指定的计算的数据视图。
通过使用流,我们可以说明想要完成什么任务,而不是说明如何去实现它。我们将操作的调度留给具体实现去解决。
例子,计算树中字数迭代与流实现的比较
流的版本比循环版本要更加容易阅读,因为我们不必扫描整个代码去查找过滤和计数操作,方法名皆可以直接告诉我们其代码意欲何为。而且,循环需要非常详细的指定操作的顺序,而流确能够以想要的任何方式来调度这些操作,只要结果是正确的即可。
**流表面上看起来和集合类似,都可以让我们转换和获取数据,但是他们之间存在着显著的差异 **
- 流并不存储其元素。这些元素可能存储在底层的集合中,或者是按需生成的。
- 流的操作不会修改其数据源,例如
filtter
方法不会从新的流中移除元素,而是生成一个新的流,其中不包含被过滤掉的元素- 流的操作时尽可能惰性执行的。这意味着直至需要结果时,操作才会执行。
流执行的顺序
- 创建一个流
- 指定将初始流转换为其他流的中间操作,可能包含多个步骤
- 应用终止操作,从而产生结果。
2、API介绍
public interface Stream<T> extends BaseStream<T, Stream<T>> {
}
A sequence of elements supporting sequential and parallel aggregate operations. The following example illustrates an aggregate operation using Stream
and IntStream
:
int sum = widgets.stream() //widgets是一个Collection<Wiget> ;创建一个Widget对象的流
.filter(w -> w.getColor() == RED)//过滤使得这个流只包含红色的Widget
.mapToInt(w -> w.getWeight())//将它转换为一个整型代表
.sum();//计算所有的weight
除了Stream
, there are primitive specializations for IntStream
, LongStream
, and DoubleStream
, all of which are referred to as “streams” and conform to the characteristics and restrictions described here.
为了执行计算,将流操作组合到流管道中。流管道包含一个源(可能是一个数组,一个集合,一个函数生成器,一个I/O通道),零个或多个中间操作(将一个流转换为另一个流,例如filter(Predicate)
和一个终端操作(产生结果或副作用,例如count()
或forEach(Consumer).
流是懒惰的;仅在启动终端操作时才对源数据进行计算,并且仅在需要时才使用源元素。
集合和数据流虽然具有表面上的相似性,但它们具有不同的目标.主要涉及对其元素的有效管理和访问。相比之下,流不提供直接访问或操纵其元素的方法
,而与声明性地描述其源以及将在该源上聚合执行的计算操作有关。但是,如果提供的流操作未提供所需的功能,则BaseStream.iterator()
和BaseStream.spliterator()
操作可用于执行受控的遍历。
类参数始终是功能接口(例如)的实例 Function
,并且通常是lambda表达式或方法引用。除非另有说明,否则这些参数必须 为非null。
方法总结
修饰符和类型 | 方法 | 描述 |
---|---|---|
boolean | allMatch(Predicate predicate) | 返回此流的所有元素是否与提供的谓词匹配。 |
boolean | anyMatch(Predicate predicate) | 返回此流的任何元素是否与提供的谓词匹配。 |
static Stream.Builder | builder() | 返回的构建器Stream 。 |
R | collect(Collector collector) | 使用对此流的元素执行可变还原操作 Collector 。 |
static Stream | concat(Stream a, Stream b) | 创建一个延迟串联的流,其元素是第一个流的所有元素,后跟第二个流的所有元素。 |
long | count() | 返回此流中的元素计数。 |
Stream | distinct() | 返回由该流的不同元素组成的流(根据 Object.equals(Object) )。 |
default Stream | dropWhile(Predicate predicate) | 如果删除了与给定谓词匹配的元素的最长前缀,则返回此流(如果此流是有序的),该流由该流的其余元素组成。 |
static Stream | empty() | 返回一个空序列Stream 。 |
Stream | filter(Predicate predicate) | 返回一个包含与此给定谓词匹配的流元素的流。 |
Optional | findAny() | 返回Optional 描述流中某些元素的描述;Optional 如果流为空,则返回空。 |
Optional | findFirst() | 返回Optional 描述此流的第一个元素的描述;Optional 如果流为空,则返回空。 |
Stream | flatMap(Function> mapper) | 返回一个流,该流包括将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。 |
DoubleStream | flatMapToDouble(Function mapper) | 返回一个DoubleStream 结果,该结果由将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。 |
IntStream | flatMapToInt(Function mapper) | 返回一个IntStream 结果,该结果由将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。 |
LongStream | flatMapToLong(Function mapper) | 返回一个LongStream 结果,该结果由将流中的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容而得到的结果。 |
void | forEach(Consumer action) | 为此流的每个元素执行一个动作。 |
void | forEachOrdered(Consumer action) | 如果流具有定义的遇到顺序,则按流的遇到顺序对此流的每个元素执行操作。 |
static Stream | generate(Supplier s) | 返回无限的顺序无序流,其中每个元素均由提供的生成Supplier 。 |
static Stream | iterate(T seed, Predicate hasNext, UnaryOperator next) | 以给定谓词为条件,返回Stream 通过将给定next 函数迭代应用到初始元素而产生的顺序有序hasNext 。 |
static Stream | iterate(T seed, UnaryOperator f) | 返回一个无限连续有序Stream 通过函数的迭代应用产生f 为初始元素seed ,产生Stream 包括seed ,f(seed) , f(f(seed)) ,等。 |
Stream | limit(long maxSize) | 返回由该流的元素组成的流,其maxSize 长度被截断为不超过长度。 |
Stream | map(Function mapper) | 返回一个流,该流包含将给定函数应用于此流的元素的结果。 |
DoubleStream | mapToDouble(ToDoubleFunction mapper) | 返回DoubleStream 由将给定函数应用于此流的元素的结果组成的。 |
IntStream | mapToInt(ToIntFunction mapper) | 返回IntStream 由将给定函数应用于此流的元素的结果组成的。 |
LongStream | mapToLong(ToLongFunction mapper) | 返回LongStream 由将给定函数应用于此流的元素的结果组成的。 |
Optional | max(Comparator comparator) | 根据提供的返回此流的最大元素 Comparator 。 |
Optional | min(Comparator comparator) | 根据提供的返回此流的最小元素 Comparator 。 |
boolean | noneMatch(Predicate predicate) | 返回此流中是否没有元素与提供的谓词匹配。 |
static Stream | of(T t) | 返回一个Stream 包含单个元素的序列。 |
static Stream | of(T... values) | 返回其元素为指定值的顺序有序流。 |
static Stream | ofNullable(T t) | 返回一个Stream 包含单个元素的序列,如果不为null,则返回null Stream 。 |
Stream | peek(Consumer action) | 返回由该流的元素组成的流,并在从结果流中消耗元素时对每个元素另外执行提供的操作。 |
Optional | reduce(BinaryOperator accumulator) | 执行减少有关此流的元件,使用 缔合累积功能,并返回一个Optional 描述该降低的值,如果有的话。 |
T | reduce(T identity, BinaryOperator accumulator) | 使用提供的标识值和关联 累加函数对此流的元素 执行归约,然后返回归约后的值。 |
U | reduce(U identity, BiFunction accumulator, BinaryOperator combiner) | 执行减少有关此流的元件,使用所提供的身份,积累和组合功能。 |
Stream | skip(long n) | 在丢弃流的第一个n 元素之后,返回由该流的其余元素组成的流。 |
Stream | sorted() | 返回由该流的元素组成的流,并根据自然顺序排序。 |
Stream | sorted(Comparator comparator) | 返回由该流的元素组成的流,并根据提供的进行排序Comparator 。 |
default Stream | takeWhile(Predicate predicate) | 如果此流是有序的,则返回一个流,该流由与此流中匹配给定谓词的元素的最长前缀组成。 |
Object[] | toArray() | 返回包含此流元素的数组。 |
A[] | toArray(IntFunction generator) | 返回一个包含此流元素的数组,使用提供的generator 函数分配返回的数组以及分区执行或调整大小可能需要的任何其他数组。 |
2、流的创建
使用Collection接口的stream方法将任何集合转化为一个流
使用Stream.of()
使用Arrays.stream(array,from,to)
静态的Files,lines方法会返回一个包含了文件中所有行的Stream
3、常用的方法
3.1、filter
流的转换会产生一个新的流,它的元素派生自另一个流中的元素
filter的引元是
Predicate<T>
,即从T
到boolean
的函数
/**
* Returns a stream consisting of the elements of this stream that match
* the given predicate.*/
Stream<T> filter(Predicate<? super T> predicate);
//将一个字符串流转换为只包含长单词的另一个流
Stream<String> longwords = wordlist.stream().filter(w->w.length()>12);
3.2、map
在使用
map
时,会有一个函数应用到每个元素,并且其结果是包含了应用该函数后所产生的所有结果流
//map函数
//将所有单词都转换为小写
Stream<String> lowercaseWords = wordlist.stream().map(String::toLowerCase);
//产生的流中包含了所有单词的首字母
Stream<String> filterLetters = wordlist.stream().map(s->s.substring(0,1));
3.3、抽取子流
stream.limit(n)
返回一个新的流,它在n个元素之后结束
stream.skip(n)
它会丢弃前n个元素
3.4、简单约简
约简是一种终结操作(terminal operation),它会将流约简介为可以在程序中使用的非流值
count
返回流中元素的数量
max和min
这些方法的返回值是一个类型
Optional<T>
的值,它要么在其中包含了答案,要么表示没有任何值(因为碰巧流为空)
3.5、收集结果
iterator()
产生可以用来访问元素的就是风格的迭代器
forEach()
将某个函数应用于每个元素
toArray()
获得由流的元素组成的数组