相信兄弟萌在学习时碰到过这样的代码吧:

List<String> list = new ArrayList();
list.stream().forEach(a-> System.out.println(a));

我相信大家初次见到这种代码跟我一样,这 TM 是个啥?能看出来有一个 Lambda 表达式,另外这个 stream 是个啥?

有没有一点像 Steam,游戏下载平台,可以玩吃鸡、CSGO,扯远了,两者毫无关系。

下面我们来揭开 stream 的秘密,Go!

1.集合处理数据的弊端

欸,不是讲 stream 吗?怎么讲到集合的处理数据了。别急,我们从集合处理数据的弊端来引入 stream。

当我们需要对集合中的元素进行操作时,除了必要的添加、删除、获取外,最典型的就是集合遍历。我们来体验集合操作数据的弊端,需求如下:

一个 ArrayList 集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰。

需求:

  1. 拿到所有姓张的
  2. 拿到名字长度为 3 个字的
  3. 打印这些数据
public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");//1.拿到所有姓张的ArrayList<String> zhangList = new ArrayList<String>(); //{"张无忌","张强","张三丰"}for (String name : list) {if(name.startsWith("张")){zhangList.add(name);}}//2.拿到名字长度为3个字的ArrayList<String> threeList = new ArrayList<String>();//{"张无忌","张三丰"}for (String name : zhangList) {if(name.length() == 3){threeList.add(name);}}//3.打印这些数据              //{"张无忌","张三丰"}for (String name : threeList) {System.out.println(name);}}

可以看出:每个需求都要遍历一次集合,还要搞一个新集合来装数据,非常麻烦。

2.Stream 流介绍

Stream 流不是一种数据结构,不保存数据,而是对集合中的数据进行加工处理。Stream 流式思想类似于工厂车间的 “生产流水线”。

注意:Stream 流和 IO 流(InputStream/OutputStream)没有任何关系,请暂时忘记对传统 IO 流的固有印象


下面我们来看看借助 Stream 流来改造上面的代码:

public static void main(String[] args) {ArrayList<String> list = new ArrayList<String>();Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");list.stream().filter((s)->{return s.startsWith("张");}).filter((s)->{return s.length() == 3;}).forEach((s)->{System.out.println(s);});}

3.获取 Stream 流的两种方式

获取一个流非常简单,有以下两种常用的方式:

  1. 所有的 Collection 集合都可以通过 .stream( ) 方法来获取流
  2. 使用 Stream 接口的 .of( ) 静态方法,可以获取流
public static void main(String[] args) {//方式1:根据Collection获取流//Collection接口中有一个默认的方法:default Stream<E> stream()List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();Set<String> set  = new HashSet<>();Stream<String> stream2 = set.stream();//方式2:Stream中的静态方法of获取流,应用场景:放数组//static<T> Stream<T> of(T... values) {Stream<String> stream3 = Stream.of("aa", "bb", "cc");String[] strs = {"aa","bb","cc"};Stream<String> stream4 = Stream.of(strs);//基本类型的数组行不行?  这是不行的,会将整个数组看作一个元素进行操作int[] arr = {11,22,33};//这里流操作的类型是 int[],将整个数组看作一个元素来操作Stream<int[]> stream5 = Stream.of(arr);}

4.Stream 常用方法和注意事项


终结方法:返回值类型不再是 Stream 类型的方法,不再支持链式调用。常见的终结方法有:

  1. count
  2. foreach
  3. anyMatch & allMatch & noneMatch
  4. findAny & findFirst
  5. reduce
  6. max & min 聚合方法都是终止操作

非终结方法:又叫函数拼接方法,值返回值类型仍然是 Stream 类型的方法,支持链式调用(除了终结方法外,其与方法均为非终结方法)。

Stream 注意事项

  1. Stream 只能操作一次
  2. Stream 方法返回的是新的流
  3. Stream 不调用终结方法,中间的操作不会执行
public static void main(String[] args) {Stream<String> stream = Stream.of("aa", "bb", "cc");//1. Stream 只能操作一次//long count = stream.count(); //执行成功//long count2 = stream.count();//执行报错//2. Stream 方法返回的是新的流//Stream<String> limit = stream.limit(1);//两个流不是同一个对象//System.out.println("stream"+stream);//System.out.println("limit"+limit);//3.Stream 不调用终结方法,中间的操作不会执行//这里只有调用了 count()(终结方法),中间的操作才会执行stream.filter((s)->{System.out.println(s);return true;}).count();}

5.Stream API

Stream API 能让我们快速完成许多复杂的操作,如:筛选、切片、映射、查找、去除重复、统计、匹配和归约。

由于 Stream API 太多了,我们这里只重点讲几个常见的。

forEach

forEach 用来遍历流中的数据。

@Test
public void testForEach(){List<String> list  = new ArrayList<>();Collections.addAll(list,"Mary","Lucy","James","Johnson","Steve");list.stream().forEach((s)->{System.out.println(s);});
}

count

count 用来统计其中元素的个数,该方法返回一个 long 值代表元素个数。

@Test
public void testCount(){List<String> list  = new ArrayList<>();Collections.addAll(list,"Mary","Lucy","James","Johnson","Steve");long count = list.stream().count();System.out.println(count);  //5}

filter

filter 用于过滤数据,返回符合过滤条件的数据。

@Test
public void testFilter(){List<String> list  = new ArrayList<>();Collections.addAll(list,"Mary","Lucy","James","Johnson","Steve");//得到名字长度为4个字的人list.stream().filter((s)->{return s.length() == 4;}).forEach((s)->{System.out.println(s);});
}

map

如果需要将流中的元素映射到另一个流中,可以使用 map 方法。

@Test
public void testMap(){Stream<String> original = Stream.of("11", "22", "33");//Map 可以将一种类型的流转换成另一种类型的流//将 Stream 流汇总的字符串转成 IntegerStream<Integer> integerStream = original.map((s) -> {return Integer.parseInt(s);});}

distinct

distinct 用来去除集合中重复的数据。

@Test
public void testDistinct(){Stream<Integer> stream = Stream.of(22,33,22,11,33);/*stream.distinct().forEach((s)->{System.out.println(s);});*/Stream<String> stream1 = Stream.of("aa", "bb", "aa", "bb", "cc");stream1.distinct().forEach(s-> System.out.println(s));}/*** distinct 对自定义对象去除重复(重写hashcode和equals,否则不会去重)*/
@Test
public void testDistinct2(){Stream<Person> stream = Stream.of(new Person("貂蝉", 18),new Person("杨玉环", 20),new Person("杨玉环", 20),new Person("西施", 16),new Person("西施", 16),new Person("王昭君", 25));stream.distinct().forEach(System.out::println);}

reduce

如果需要将所有数据归纳得到一个数据,可以使用 reduce 方法。

@Test
public void testReduce(){//T reduce(T identity, BinaryOperator<T> accumulator);//T identity:默认值//BinaryOperator<T> accumulator:对数据进行处理的方式/*Integer reduce = Stream.of(4, 5, 3, 9).reduce(0, (x, y) -> {//x=0, y=4//x=4, y=5//x=9, y=3//x=12, y=9System.out.println("x="+x+", y="+y);return x + y;});System.out.println("reduce="+reduce); //21*///获取最大值Integer max = Stream.of(4, 5, 3, 9).reduce(0, (x, y) -> {return x > y ? x : y;});System.out.println("最大值:"+max);
}

6.收集 Stream 流中的结果

对流操作完成之后,如果需要将流的结果保存到数据或集合中,可以收集流中的数据。

6.1 收集到集合中

Stream 流提供 collect 方法,其参数需要一个 java.util.stream.Collector<T,A,R> 接口对象来指定收集到哪种集合。java.util.Collectors 类提供一些方法,可以作为 Collector 接口的实例:

//这里转换的 list 是 ArrayList,如果想要转换成特定的 list,需要使用 toCollection 方法
public static <T> Collector<T,?,List<T>> toList( ):转换为 List 集合//这里转换的 set 是 HashSet,如果需要特别指定 set,那么需要使用 toCollection 方法
public static <T> Collector<T,?,List<T>> toSet( ):转换为 Set 集合
@Test
public void testStreamToCollection(){Stream<String> stream = Stream.of("aa", "bb", "cc");//将流中的数据收集到集合中/*List<String> list = stream.collect(Collectors.toList());System.out.println("list = "+list);*/   //list = [aa, bb, cc]/*Set<String> set = stream.collect(Collectors.toSet());System.out.println("set = "+set);  //set = [aa, bb, cc]*///收集到指定的集合中ArrayList//如果想要转换成特定的list,需要使用toCollection方法LinkedList<String> collect = stream.collect(Collectors.toCollection(LinkedList::new));
}

6.1 收集到数组中

//将流中的数据收集到数组中
@Test
public void testStreamToArray(){Stream<String> stream = Stream.of("aa", "bb", "cc");//转成object数组不方便Object[] objects = stream.toArray();//String[]String[] strings = stream.toArray(String[]::new);for (String string : strings) {System.out.println("string = "+string);}
}

带你看看JDK8新特性:Stream流相关推荐

  1. stream流_最详细的JDK8新特性————Stream流

    Stream流 在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊 端. 传统集合的多步遍历代码: 几乎所有的集合(如Collect ...

  2. Java JDK8新特性Stream流

    1.Stream流 1. 流,支持处理数据处理操作的源生成的元素序列.流有两个重要特性:1流水线:很多流操作本身会返回一个流,这样多的操作就可以链接起来,形成一个大的流水线.2,内部迭代.流的迭代是在 ...

  3. JDK8 新特性Stream流的常用方法

    流表示包含着一系列元素的集合,我们可以对其做不同类型的操作,用来对这些元素执行计算 二.中间流的部分应用 中间操作会再次返回一个流,所以,我们可以链接多个中间操作,注意这里是不用加分号的. /* St ...

  4. JDK8新特性Stream流使用详解

    Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达 ...

  5. Java8新特性Stream流详解

    陈老老老板 说明:新的专栏,本专栏专门讲Java8新特性,把平时遇到的问题与Java8的写法进行总结,需要注意的地方都标红了,一起加油. 本文是介绍Java8新特性Stream流常用方法超详细教学 说 ...

  6. java的collect用法_java8新特性:stream流中collect用法

    java8新特性:stream流中collect用法 java8新特性:stream流中collect用法 1.toList List collectList = Stream.of(1, 2, 3, ...

  7. Java复习第11天---11.4---Java8新特性---Stream流常用方法3和综合案例

    Java复习第11天---11.4---Java8新特性---Stream流常用方法3和综合案例 目录 文章目录 1.count:计数-终结方法 2.limit:取前几个元素-延迟方法 3.skip: ...

  8. Java复习第11天---11.3---Java8新特性---Stream流特点和常用方法2

    Java复习第11天---11.3---Java8新特性---Stream流特点和常用方法2 目录 文章目录 1.Stream流特点 2.filter:过滤 3.map:映射 ***后记*** : 内 ...

  9. Java复习第11天---11.2---Java8新特性---Stream流获取方式和常用方法1

    Java复习第11天---11.2---Java8新特性---Stream流获取方式和常用方法1 目录 文章目录 1.Stream流的2中获取方式 1.1.集合的stream方法 1.2.Stream ...

  10. 【JavaSE之JDK8新特性】三万字详文带你了解JDK8新特性

    JDK8新特性 一.Lambda 1.1需求分析 2.Lambda表达式的初级体验 3.Lambda表达式的语法规则 3.1.Lambda练习1 3.2.Lambda表达式练习2 4.Function ...

最新文章

  1. 第十七届全国大学生智能车竞赛航天智慧物流创意组-第二次线上技术培训
  2. shell批量监控网站状态码
  3. Parity Alternated Deletions
  4. 亲手完成四大企业实战项目,挑战Python全栈高薪岗位!
  5. ionic overflow:auto失效
  6. 加大weblogic在Linux内存,在linux运行weblogic出现运行内存不足错误,求鞭挞....
  7. ggplot 非常难调的参数
  8. html.actionlink 锚点,razor - 从@ Html.ActionLink MVC 4将参数传递给控制器
  9. 先批标准化还是先激活
  10. gateway网关_公司要把网关Zuul换成Gateway,再难也得顶上
  11. 集成海康威视Sadp SDK实现设置设备参数配置
  12. 【STC单片机学习】第八课:单片机的LED点阵
  13. JarvisOJ 逆向Writeup
  14. 11g OCM 考试感悟
  15. SKY光遇功能辅助脚本介绍 新手入门了解SKY光遇
  16. 给学弟学妹肝的一篇Java学习路线,保证学弟学妹们大三大四的时候顺利找到实习 Offer
  17. ABB 120 六轴机械手臂编程调试(四) 三菱plc控制器配套程序
  18. Apache的管理及优化——中篇{Apache的访问控制(黑白名单,用户密码认证)、Apache的虚拟主机}
  19. Linux 解压缩文件到指定目录
  20. 火狐和IE之间的区别

热门文章

  1. 快速查询大量的顺丰快递单号物流,并分析派件延误
  2. innovus停止当前命令_Innovus教程 - Flow系列 - 摆放宏单元(理论+实践+命令)
  3. 计算机管理策略设置,windows10系统管理员设置了系统策略解决方法介绍
  4. 邮件服务器的协议有哪几个?有什么特点?
  5. Linux 共享存储服务
  6. php trip_tags,PHP之字符串函数
  7. 柯尼卡美能达Konica Minolta bizhub C226 默认管理员密码
  8. 【app性能测试】Python脚本监控app指标
  9. 各种简历模板大全,让人事吸引的利器
  10. 「WGCLOUD」支持监测Android(安卓)终端手机的状态吗