Stream
谈到Java8新特性,必不可少的stream一定要写一篇笔记🤦
那到底什么是stream呢?
Lambda表达式是Stream API的基石,所以先对lambda做一个回顾
这是我之前写的关于Lambda表达式的学习笔记:
这篇是新发现的,也有讲到stream:https://www.jianshu.com/p/5548ce392db7
原理
将要处理的元素看做一种流,流在管道中传输,并且可以在管道的节点上处理,包括过滤筛选、去重、排序、聚合等。元素流在管道中经过中间操作 的处理,最后由最终操作 得到前面处理的结果
最开始的数据是小水滴,经过各种"拦截器"的处理后,有的被丢弃,有的变大了,有的加了颜色,有的变成了三角形,最后它们都变成了带有颜色的圆,最后被我们放到结果集中。
stream可以为你省去for嵌套for的操作
but , attention❗
特性
- 基于集合或者序列
- Stream自己不会存储元素
- Stream不会改变源对象,因为每个操作都是函数式的。相反,会返回一个持有结果的新Stream
- Stream操作是延迟执行的。意味着要等到需要结果的时候才执行
- 流不存储值,也不能重复使用,数据通过管道的方式进行操作(后面有栗子)
三步骤
创建Stream
一个数据源(如:集合、数组),获取一个流
中间操作
一个中间操作链,对数据源的数据进行处理
终止操作(终端操作)
一个终止操作,执行中间操作链。并产生结果
上面图片简化版:
1、创建stream
//模板
default Stream<E> stream():返回一个顺序流
default Stream<E> parallelStream():返回一个并行流
有数组创建流:static <T> Stream<T> stream(T[] array):返回一个流
由值创建流:public static<T> Stream<T> of(T… values):返回一个流
由函数创建流:创建无限流
迭代:public static<T> Stream<T> iterate(final T seed,final UnaryOperator<T> f)
生成:public static<T> Stream<T> generate(Supplier<T> s)
2、中间操作
3、最终操作
collect接口还有很多可以展开的
接下去看几个小应用吧
预备tips
:: 操作符将方法名和对象或类的名字分割开来,主要有下面三种:
1、对象 :: 实例方法
2、类 :: 静态方法
3、类 :: 实例方法
System.out::println
是一个方法引用,等同于lambda表达式x -> System.out.println(x)
Math::pow
== (x,y) -> Math.pow(x,y)
第三种情况,第一个参数会称为执行方法的对象,如String::compareToIgnoreCase
== (x,y) -> x.compareToIgnoreCase(y)
this::equals
== x -> this.equals(x),super::equals
== super.equals(x)
//打印元素的平方
int[] nums = {1,2,3};
Arrays.stream(nums).map(i->i*i).forEach(System.out::println);
//输出
1
4
9
// 所有偶数累加求和
int[] nums = {1,2,3,4,5,6};
System.out.println( Arrays.stream(nums).map(i -> i % 2 == 0 ? i : 0).reduce(0, Integer::sum) );
//输出
12
// flatMap处理嵌套的list
List< List<Integer> > example =Arrays.asList( Arrays.asList(1,2,3),Arrays.asList(11,12,13) );
example.stream().flatMap( list->list.stream() ).map(i->2*i).forEach( i->System.out.println(i));
//输出
1
4
6
121
144
169
⚠
1、流只能使用一次,不能重复:
Stream<Integer> example = Stream.of(11,22,33);
example.forEach( i->System.out.println(i) );
example.reduce(0, Integer::sum);
输出:
2、
流延迟操作
Stream<Integer> exampl= Stream.of(11,70,23,46,50,100,10,24,18,19,2);
exampl.map( i->{System.out.println(i); return i;} );
//流只要在终止操作(及早求值)时,才会对数据统一做操作,在没有遇到求值操作的时候,惰性操作代码不会被执行
输出:
3、流不会改变原来的数据, 如一个数组 经过流 输出操作结果,但原数组并未改变
关于stream的知识点真的很多,它是Java8 新特性中十分十分重要的,这篇博客需要一直更新🖊
如有不正之处,欢迎指正🙇
主要学习博客: