Stream流简单案例对比
说到Stream流会让人想到IO流,然而这完全是2个概念,Stream流得益于lambda表达式接口实现,解决了集合的弊端,是JDK1.8以后出现的

弊端案例如上,我们想要对一堆姓名集合筛选出张开头,而且长度为3的名字,我们代码如上,需要多次循环便利了,性能很差(虽然感觉可以将组合条件处理,但是为了展示弊端,先这么写吧)

我们可以使用流式处理,1.8以后,集合.stream()可以获得其流,流有filter过滤方法,参数是predicate接口,返回的仍然是流,既然是predicate,那我们只要传入lambda表达式即可,保证返回boolean值,forEach是流的遍历方法,里面是Consumer消费者接口,我们同样传入lambda表达式即可,
可以看见代码变得非常简洁
Stream流思想
流思想来源于工厂流水线

我们流式思想就是拼接生产线,如上,集合经过filter过滤,输出还是流,流经过映射,可以改变数据类型,skip可以跳过流某些部分,count可以统计流的元素,这里filter,map,skip都没有对集合进行操作,只是实现搭接生产线,只有执行count,模型才真正执行操作

如上filter,map,skip都是对模型操作,输出还是流,java中Streamb并不存储元素,而是按需计算,stream流还有2个基本特征Pipelining管道,内部迭代(我们之前讲的forEach)
我们使用stream流分3步,1获取数据源,2进行转换,讲集合等转换为stream流,3执行操作获取相关结果
获取stream流

有2种方法,jdk8以后java.util.stream.Stream<T>是流接口,使用静态方法of获取对应的流,还有就是Collection集合.stream()可以获取流(map集合不可以)
static <T> Stream<T> of (...values) 可以看到of是可变参数,我们可以传入数组

如上,如果是Collection集合,那我们就可以使用stream()获取流了,对于数组,我们可以使用Stream接口的静态方法,其中数组我们基本类型要使用泛型,map集合因为是双列无法直接使用流,只能键或值单独获取流
Stream流常用方法
获取到流后,就需要使用流的方法

方法分为延迟方法和终结方法,延迟方法返回仍然是Stream接口类型,可以链式调用,而终结方法返回不再是Stream接口,其方法有count,forEach
forEach方法
这个forEach和循环的for-each不一样,
函数void forEach(Comsumer<? super T> action),可以看到其参数为Consumer接口
我们知道Consumer接口有void accept(T t)抽象方法

如上,我们给数组arr每个元素+3输出,注意了,此方法为终结方法,使用了就不能再使用流其他方法
filter方法

我们可以看到filter方法参数为Predicate接口,其有test抽象方法,通过test返回的boolean值,决定对输出流的元素去留

代码如上,对1,2,3,4,5中的偶数挑出来

我们将流拆分成s1,s2,可以看到我们流过了s1后,s1的流就关闭了,我们调用s1就会报错,流只能使用一次,到了终结方法,所有流都关闭,如下,我们再次调用s2的也是不可以

map方法

其本质是将流转换为另一个流,同时,数据类型可以发生变化,参数为Function接口,我们知道其抽象方法为apply方法

如上,我们将数字转变成string
Count方法
用于统计个数,long count(),注意返回类型是long,是终结方法

limit方法
延迟方法,只取前n个,Stream<T> limit(long n)

skip方法
延迟方法,跳过前几个,Stream<T> skip(long n)

感觉没啥说的
Concat方法
延迟方法,将2个流拼接返回一个流,参数前后决定顺序,Stream<T> concat(Stream<?extends T> s1,Stream<?extends T> s2)

网友评论