带你看看JDK8新特性:Stream流
相信兄弟萌在学习时碰到过这样的代码吧:
List<String> list = new ArrayList();
list.stream().forEach(a-> System.out.println(a));
我相信大家初次见到这种代码跟我一样,这 TM 是个啥?能看出来有一个 Lambda 表达式,另外这个 stream 是个啥?
有没有一点像 Steam,游戏下载平台,可以玩吃鸡、CSGO,扯远了,两者毫无关系。
下面我们来揭开 stream 的秘密,Go!
1.集合处理数据的弊端
欸,不是讲 stream 吗?怎么讲到集合的处理数据了。别急,我们从集合处理数据的弊端来引入 stream。
当我们需要对集合中的元素进行操作时,除了必要的添加、删除、获取外,最典型的就是集合遍历。我们来体验集合操作数据的弊端,需求如下:
一个 ArrayList 集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰。
需求:
- 拿到所有姓张的
- 拿到名字长度为 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 流的两种方式
获取一个流非常简单,有以下两种常用的方式:
- 所有的 Collection 集合都可以通过 .stream( ) 方法来获取流
- 使用 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 类型的方法,不再支持链式调用。常见的终结方法有:
- count
- foreach
- anyMatch & allMatch & noneMatch
- findAny & findFirst
- reduce
- max & min 聚合方法都是终止操作
非终结方法:又叫函数拼接方法,值返回值类型仍然是 Stream 类型的方法,支持链式调用(除了终结方法外,其与方法均为非终结方法)。
Stream 注意事项
- Stream 只能操作一次
- Stream 方法返回的是新的流
- 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流相关推荐
- stream流_最详细的JDK8新特性————Stream流
Stream流 在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊 端. 传统集合的多步遍历代码: 几乎所有的集合(如Collect ...
- Java JDK8新特性Stream流
1.Stream流 1. 流,支持处理数据处理操作的源生成的元素序列.流有两个重要特性:1流水线:很多流操作本身会返回一个流,这样多的操作就可以链接起来,形成一个大的流水线.2,内部迭代.流的迭代是在 ...
- JDK8 新特性Stream流的常用方法
流表示包含着一系列元素的集合,我们可以对其做不同类型的操作,用来对这些元素执行计算 二.中间流的部分应用 中间操作会再次返回一个流,所以,我们可以链接多个中间操作,注意这里是不用加分号的. /* St ...
- JDK8新特性Stream流使用详解
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达 ...
- Java8新特性Stream流详解
陈老老老板 说明:新的专栏,本专栏专门讲Java8新特性,把平时遇到的问题与Java8的写法进行总结,需要注意的地方都标红了,一起加油. 本文是介绍Java8新特性Stream流常用方法超详细教学 说 ...
- java的collect用法_java8新特性:stream流中collect用法
java8新特性:stream流中collect用法 java8新特性:stream流中collect用法 1.toList List collectList = Stream.of(1, 2, 3, ...
- Java复习第11天---11.4---Java8新特性---Stream流常用方法3和综合案例
Java复习第11天---11.4---Java8新特性---Stream流常用方法3和综合案例 目录 文章目录 1.count:计数-终结方法 2.limit:取前几个元素-延迟方法 3.skip: ...
- Java复习第11天---11.3---Java8新特性---Stream流特点和常用方法2
Java复习第11天---11.3---Java8新特性---Stream流特点和常用方法2 目录 文章目录 1.Stream流特点 2.filter:过滤 3.map:映射 ***后记*** : 内 ...
- Java复习第11天---11.2---Java8新特性---Stream流获取方式和常用方法1
Java复习第11天---11.2---Java8新特性---Stream流获取方式和常用方法1 目录 文章目录 1.Stream流的2中获取方式 1.1.集合的stream方法 1.2.Stream ...
- 【JavaSE之JDK8新特性】三万字详文带你了解JDK8新特性
JDK8新特性 一.Lambda 1.1需求分析 2.Lambda表达式的初级体验 3.Lambda表达式的语法规则 3.1.Lambda练习1 3.2.Lambda表达式练习2 4.Function ...
最新文章
- 第十七届全国大学生智能车竞赛航天智慧物流创意组-第二次线上技术培训
- shell批量监控网站状态码
- Parity Alternated Deletions
- 亲手完成四大企业实战项目,挑战Python全栈高薪岗位!
- ionic overflow:auto失效
- 加大weblogic在Linux内存,在linux运行weblogic出现运行内存不足错误,求鞭挞....
- ggplot 非常难调的参数
- html.actionlink 锚点,razor - 从@ Html.ActionLink MVC 4将参数传递给控制器
- 先批标准化还是先激活
- gateway网关_公司要把网关Zuul换成Gateway,再难也得顶上
- 集成海康威视Sadp SDK实现设置设备参数配置
- 【STC单片机学习】第八课:单片机的LED点阵
- JarvisOJ 逆向Writeup
- 11g OCM 考试感悟
- SKY光遇功能辅助脚本介绍 新手入门了解SKY光遇
- 给学弟学妹肝的一篇Java学习路线,保证学弟学妹们大三大四的时候顺利找到实习 Offer
- ABB 120 六轴机械手臂编程调试(四) 三菱plc控制器配套程序
- Apache的管理及优化——中篇{Apache的访问控制(黑白名单,用户密码认证)、Apache的虚拟主机}
- Linux 解压缩文件到指定目录
- 火狐和IE之间的区别
热门文章
- 快速查询大量的顺丰快递单号物流,并分析派件延误
- innovus停止当前命令_Innovus教程 - Flow系列 - 摆放宏单元(理论+实践+命令)
- 计算机管理策略设置,windows10系统管理员设置了系统策略解决方法介绍
- 邮件服务器的协议有哪几个?有什么特点?
- Linux 共享存储服务
- php trip_tags,PHP之字符串函数
- 柯尼卡美能达Konica Minolta bizhub C226 默认管理员密码
- 【app性能测试】Python脚本监控app指标
- 各种简历模板大全,让人事吸引的利器
- 「WGCLOUD」支持监测Android(安卓)终端手机的状态吗