Stream是jdk1.8提供的新的流式编程,它不是集合也不保存任何内容,可以像build对象一样,一直点点点最后跟一个终结语句;
研究Stream之前需要先了解:
- 新的接口定义:jdk1.8——接口新的默认方法和静态方法_FlyLikeButterfly的博客-CSDN博客
- 函数式接口:jdk1.8——函数式接口_FlyLikeButterfly的博客-CSDN博客
- Lambda表达式:jdk1.8——Lambda表达式_FlyLikeButterfly的博客-CSDN博客
- 方法引用:jdk1.8——方法引用_FlyLikeButterfly的博客-CSDN博客
Stream的特性:
注:对于基本数据类型,另外有三个包装Stream类型:IntStream、LongStream、DoubleStream,这三个类型跟Stream类稍微有些差别,例如不需要泛型、特有的方法等;
生成Stream的方式:
- 用Collection的stream()和parallelStream()
- Arrays的stream()
- Stream类的静态方法of()、iterate()、generate()
- BufferedReader.lines()
- Pattern的splitAsStream()
- IntStream.range()
- Files.walk()
- Random的ints()
- BitSet.stream()
- JarFile.stream()
- 通过Stream.builder()的builde()
Stream的操作类型:
-
Intermediate(中间操作)
一个流后面可以跟0个或多个中间操作,主要是对数据做一些过滤映射操作,然后返回流交给下一个操作,中间操作是惰性的,只会记录操作过程,不会真正开始遍历数据;中间操作分无状态和有状态两种操作,无状态的每个元素可单独处理,跟其他元素无关联(filter,map),有状态的元素需要知道其他元素(distinct,sorted);在并行时,某些有状态的操作可能回遍历数据多次或者缓冲大量数据(sorted不适合用并行);
-
Terminal(终止操作)
一个流只能有一个终止操作,必定是最后一个操作,执行完后流就被用完了不能再被使用,终止操作执行的时候才会真正开始遍历数据,返回数据或者执行一段代码;
-
还有一种short-circuiting(短路操作,是处理无限流时的必要不充分条件)
中间操作的短路,会产生有限的流;终止操作的短路,会在有限时间内终止;
Stream类的方法详解:
- 静态方法
builder(), concat(Stream<? extends T>, Stream<? extends T>), empty(), generate(Supplier<T>), iterate(T, UnaryOperator<T>), of(T), of(T...)
- allMatch(Predicate<? super T>)
(短路终止)元素都匹配返回true,否则false;(中间遇到不匹配立即返回flase)
- anyMatch(Predicate<? super T>)
(短路终止)存在匹配返回true,否则flase;(中间存在一个匹配立即返回true)
- collect(Supplier<R>, BiConsumer<R, ? super T>, BiConsumer<R, R>)
- collect(Collector<? super T, A, R>)
(终止)将流转换成集合和聚合元素;
- count()
(终止)返回流的元素数量;
- distinct()
(状态中间)去重,对于有序流保留第一个,无序流是随机的;
- filter(Predicate<? super T>)
(中间)过滤元素;
- findAny()
(短路终止)返回流中任意一个元素;
- findFirst()
(短路终止)返回流中第一个元素;
- forEach(Consumer<? super T>)
- forEachOrdered(Consumer<? super T>)
(终止)遍历,有序流ordered保证顺序(并行);
- flatMap(Function<? super T, ? extends Stream<? extends R>>)
- flatMapToDouble(Function<? super T, ? extends DoubleStream>)
- flatMapToInt(Function<? super T, ? extends IntStream>)
- flatMapToLong(Function<? super T, ? extends LongStream>)
(中间)扁平映射,一个映射多个;
- isParallel()
是否是并行流(继承方法);
- iterator()
返回流的迭代器(继承方法);
- limit(long)
(短路状态中间)截断流的最大长度;
- map(Function<? super T, ? extends R>)
- mapToDouble(ToDoubleFunction<? super T>)
- mapToInt(ToIntFunction<? super T>)
- mapToLong(ToLongFunction<? super T>)
(中间)映射,一对一;
- max(Comparator<? super T>)
(终止)根据比较规则返回最大值
- min(Comparator<? super T>)
(终止)根据比较规则返回最小值(compare返回<=0则返回第一个)
- noneMatch(Predicate<? super T>)
(短路终止)没有相匹配的返回true,一旦匹配立即返回false;
- close()
关闭流(继承方法);
- onClose(Runnable)
(中间)调用close()的时候触发,所有的onClose定义的runnable都会按添加顺序执行(即使有的runnable抛出异常),run中抛出的第一个异常将在close()方法中抛出,其他异常会作为抑制异常被添加到该抛出异常中(继承方法);
- parallel()
(中间)将流变成并行流(继承方法);
- sequential()
(中间)将流变成串行流(继承方法);
- peek(Consumer<? super T>)
(中间)元素在结果流中被消耗时,额外对每个元素执行该操作;
- reduce(BinaryOperator<T>)
- reduce(T, BinaryOperator<T>)
- reduce(U, BiFunction<U, ? super T, U>, BinaryOperator<U>)
(终止)对元素进行累加操作;
- skip(long)
(状态中间)丢弃前n个元素,可能返回空流;
- sorted()
(状态中间)按自然元素排序;
- sorted(Comparator<? super T>)
(状态中间)根据比较器排序;
注:reversed()反向排序是对当前整个Comparator定义的排序取反;
- spliterator()
(终止)返回流元素的拆分器(继承方法);
- toArray()
- toArray(IntFunction<A[]>)
(终止)返回A[]元素数组(IntFunction的参数为元素个数);
- unordered()
(中间)返回一个无序的流(继承方法);
IntStream的其他特有方法:
- range(int, int)
返回一个整数序列,不包括最后一个(静态方法);
- rangeClosed(int, int)
返回一个整数序列,包括最后一个(静态方法);
- asDoubleStream()
(中间)转换成DoubleStream;
- asLongStream()
(中间)转换成LongStream;
- average()
(终止)返回算数平均值的OptionalDouble对象;
- boxed()
(中间)每个元素装箱成Integer对象,返回Stream<Integer>;
- sum()
(终止)求和;
- summaryStatistics()
(终止)返回一个IntSummaryStatistics对象,该对象包括流元素的概要数据;
注:
- IntStream只有一个collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R, R> combiner)方法,需要boxed转成Stream<Integer>在用其他的collect;
- DoubleStream没有IntStream里的range、rangeClosed、asDoubleStream、asLongStream方法,其他除了类型基本一致;
- LongStream没有IntStream里的asLongStream方法,其他除了类型基本一致;
注意事项:
一个小Demo:
从Stream.of也能看得出区别:
- 基本数据类型不是对象,基本数据类型的包装类型是对象,基本数据类型是在栈上分配的,包装类型是new出来的,在堆上分配;
- 关于数组,栈上分配的一个指向堆的指针,数组是一个对象,基本数据类型的数组就只是一个数组对象(数组内的元素直接是值),而包装类型的数组里的元素也是指针(指向包装类型的对象);