手把手带你体验Stream流

前言

专注于为中小企业提供成都网站制作、成都做网站服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业日土免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了成百上千企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

只有光头才能变强。

相信也有不少的同学想要知道:Lambda表达式在工作中哪个场景会用得比较多?跟Lambda搭边的,使用 Stream流会比较多

一般人第一次看Stream流的代码,都会有点看不懂(它的代码看起来好像就不是写Java一样.),希望这篇文章能带大家入个门

一、体验Stream流

大家在自学时,大多数会学过一个程序:算出从数组元素的和,当时我们是怎么写的?一般来说是这样的:

publicstaticvoidmain(String[]args){int[]nums={1,2,3};intsum=0;for(inti:nums){sum+=i;}System.out.println("结果为:"+sum);}

如果我们使用Stream流的话,可以这样:

publicstaticvoidmain(String[]args){int[]nums={1,2,3};intsum2=IntStream.of(nums).sum();System.out.println("结果为:"+sum2);}

从 代码量上可以明显看出,用Stream流的方式会少一些。

我理解的Stream流编程就是: 某些场景会经常用到操作(求和/去重/过滤….等等),已经封装好API给你了,你自己别写了,调我给你提供的API就好了。

1.1 支持并发

回到我们最原始的代码:

publicstaticvoidmain(String[]args){int[]nums={1,2,3};intsum=0;for(inti:nums){sum+=i;}System.out.println("结果为:"+sum);}

如果我们想要for循环的内部支持并发的话,显然不太好去写。但使用Stream流的方式, 调用一个方法就可以支持并发(parallel):

publicstaticvoidmain(String[]args){int[]nums={1,2,3};intsum2=IntStream.of(nums).parallel().sum();System.out.println("结果为:"+sum2);}

优点:调API肯定是比自己写的代码量要少。

缺点:不方便调试

为什么要使用Stream流在我看来就是以上两个原因:

  • 方便并发
  • 代码量少(直接调用API)

二、如何使用Stream流?

手把手带你体验Stream流

Stream继承结构图

使用Stream流分为三步:

  1. 创建Stream流
  2. 通过Stream流对象执行中间操作
  3. 执行最终操作,得到结果
手把手带你体验Stream流

三步走

2.1 创建流

创建流我们最常用的就是 从集合中创建出流

/***返回的都是流对象*@paramargs*/publicstaticvoidmain(String[]args){Listlist=newArrayList<>();//从集合创建Streamstream=list.stream();Streamstream1=list.parallelStream();//从数组创建IntStreamstream2=Arrays.stream(newint[]{2,3,5});//创建数字流IntStreamintStream=IntStream.of(1,2,3);//使用random创建IntStreamlimit=newRandom().ints().limit(10);}

2.2 执行中间操作

怎么理解中间操作?意思是这样的:在上面我们已经能创建出Stream了,我们是对 Stream进行操作,对Stream操作返回完返回的还是Stream,那么我们称这个操作为中间操作。

手把手带你体验Stream流

中间操作 解释

比如,我们现在有个字符串my name is 007,代码如下:

Stringstr="mynameis007";Stream.of(str.split("")).filter(s->s.length()>2).map(s->s.length()).forEach(System.out::println);

分解:

1、从字符串数组创建出流对象:

Streamsplit=Stream.of(str.split(""));

2、通过流对象的API执行中间操作(filter),返回的还是流对象:

StreamfilterStream=split.filter(s->s.length()>2);

3、通过返回的流对象再执行中间操作(map),返回的还是流对象:

StreamintegerStream=filterStream.map(s->s.length());

因为中间操作返回的都是 流对象,所以我们可以 链式调用。

注意:Stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行( 惰性求值)。

比如说,peek()是一个中间操作,返回的是Stream流对象,只要它不执行最终的操作,这个Stream是不会执行的。

Stringstr="mynameis007";Stream.of(str.split("")).peek(System.out::println);//不会有信息打印

2.3 执行最终操作

最终操作返回的不再是Stream对象, 调用了最终操作的方法,Stream才会执行。还是以上面的例子为例:

Stringstr="mynameis007";Stream.of(str.split("")).peek(System.out::println).forEach(System.out::println)

这次我们加入了最终操作,所以这次的Stream流会被执行,由于中间操作和最终操作都是执行打印,所以会看到两次打印:

手把手带你体验Stream流

结果图

至于中间操作和最终操作怎么区分,我们以 返回值来看就行了。中间操作返回的是Stream实例对象,最终操作返回的不是Stream实例对象:

手把手带你体验Stream流

Stream接口的方法

最后

这篇文章主要跟大家一起初步认识一下Stream流,至于中间操作、最终操作的API讲解我就不写了(网上的教程也很多)

使用Stream的原因我认为有两个:

  1. JDK库提供现有的API,代码写起来简洁优化
  2. 方便并发。大家可以记住一个结论:在 多核情况下,可以使用 并行Stream API来发挥多核优势。在单核的情况下,我们自己写的for性能不比Stream API 差多少

网站题目:手把手带你体验Stream流
当前路径:http://myzitong.com/article/pjgpeo.html