Java8 Stream流操作
来源:互联网 发布:java arrayy.size 编辑:程序博客网 时间:2024/04/19 19:50
传统的数据处理都是用循环来解决,而不是像搜索数据库那样有具体的搜索语句,而Java8的Stream提供了很好的方案,往往一行就搞定了,而且Stream还可以链式操作,一行代码实现多个循环的功能,代码风格十分像nosql数据库,但是在实际应用中发现一个巨大的问题,就是执行耗时特别长,时间开销是传统方法的几百倍,这是一个巨大的问题。
本文主要来讨论一下如何发挥Stream的优势展示对用户管理操作
首先我们制造一个User类用来代表用户,里面有姓名年龄密码等常用字段,顺道再写个构造函数和toString(),如下
现在我们伪造一点数据,暂时就用我大学同学的名字吧:
场景一、对用户进行排序
首先我们制定一个排序规则:按照年龄大小进行排序,设计一个Comparator
传统方式排序:
输出结果:耗时0
[{"age":"5", "name":"韩凯", "password":"e123456", "gendar":"1", "hasMarried":"true"}
, {"age":"14", "name":"季恺", "password":"i123456", "gendar":"1", "hasMarried":"false"}
, {"age":"16", "name":"姜有琪", "password":"k123456", "gendar":"1", "hasMarried":"false"}
, {"age":"17", "name":"郭林杰", "password":"d123456", "gendar":"1", "hasMarried":"false"}
, {"age":"17", "name":"荆帅", "password":"j123456", "gendar":"1", "hasMarried":"true"}
, {"age":"18", "name":"蔡明浩", "password":"c123456", "gendar":"1", "hasMarried":"true"}
, {"age":"19", "name":"胡亚强", "password":"h123456", "gendar":"1", "hasMarried":"false"}
, {"age":"21", "name":"孙萍", "password":"a123456", "gendar":"2", "hasMarried":"false"}
, {"age":"21", "name":"郝玮", "password":"g123456", "gendar":"2", "hasMarried":"false"}
, {"age":"22", "name":"王旭", "password":"123456", "gendar":"1", "hasMarried":"true"}
, {"age":"22", "name":"王旭", "password":"123456", "gendar":"1", "hasMarried":"true"}
, {"age":"22", "name":"王旭", "password":"123456", "gendar":"1", "hasMarried":"true"}
, {"age":"22", "name":"韩天琪", "password":"f123456", "gendar":"2", "hasMarried":"false"}
, {"age":"23", "name":"步传宇", "password":"b123456", "gendar":"1", "hasMarried":"false"}
]
Java8的方式排序:
输出结果相同,耗时234ms从结果来看,java8 Stream操作的耗时至少是传统方法的200多倍,时间成本较大。
场景一(2)选出年龄最小的三个人
有时候我们也许并不需要获得排序的所有结果,只需要获得前几名就可以了,比如我想获得年龄最小的三个人
传统方法排序限制:
首先进行上面的排序,然后取出数组的前三个元素
耗时0Java8方式排序限制:
结果:耗时375
[{"age":"5", "name":"韩凯", "password":"e123456", "gendar":"1", "hasMarried":"true"}
, {"age":"14", "name":"季恺", "password":"i123456", "gendar":"1", "hasMarried":"false"}
, {"age":"16", "name":"姜有琪", "password":"k123456", "gendar":"1", "hasMarried":"false"}
]
场景二:去除重复数据
为了识别两个对象是否重复,需要复写User的equals方法
要实现去重,必须首先将数组的顺序严格排好,也就是相似的数据要放在一起,便于排序,所以我们要重写一下比较器
传统方法去重:
输出结果:耗时0
[{"age":"5", "name":"韩凯", "password":"e123456", "gendar":"1", "hasMarried":"true"}
, {"age":"14", "name":"季恺", "password":"i123456", "gendar":"1", "hasMarried":"false"}
, {"age":"16", "name":"姜有琪", "password":"k123456", "gendar":"1", "hasMarried":"false"}
, {"age":"17", "name":"郭林杰", "password":"d123456", "gendar":"1", "hasMarried":"false"}
, {"age":"17", "name":"荆帅", "password":"j123456", "gendar":"1", "hasMarried":"true"}
, {"age":"18", "name":"蔡明浩", "password":"c123456", "gendar":"1", "hasMarried":"true"}
, {"age":"19", "name":"胡亚强", "password":"h123456", "gendar":"1", "hasMarried":"false"}
, {"age":"21", "name":"孙萍", "password":"a123456", "gendar":"2", "hasMarried":"false"}
, {"age":"21", "name":"郝玮", "password":"g123456", "gendar":"2", "hasMarried":"false"}
, {"age":"22", "name":"王旭", "password":"123456", "gendar":"1", "hasMarried":"true"}
, {"age":"22", "name":"韩天琪", "password":"f123456", "gendar":"2", "hasMarried":"false"}
, {"age":"23", "name":"步传宇", "password":"b123456", "gendar":"1", "hasMarried":"false"}
]
Java8 去重:
Stream去重有一个先决条件,就是要去重的对象必须实现comparable接口,不能使用比较器,于是让user类implement comparable,并复写其方法compareTo,另外equals()方法与上面一样.
然后先调用stream的sorted()方法进行排序,再调用disdinct()方法进行去重,结果同上面一样,耗时249ms场景三:按条件筛选
这种场景也许是最常见的一种应用场景了,在许多元素构成的数组中筛选出我们需要的满足特定条件的元素,在这里我们把所有姓韩的筛选出来
传统方法:
结果:耗时0[{"age":"5", "name":"韩凯", "password":"e123456", "gendar":"1", "hasMarried":"true"}
, {"age":"22", "name":"韩天琪", "password":"f123456", "gendar":"2", "hasMarried":"false"}
]
Java8方法:
结果相同,耗时266ms
其中,java8采用的泛型进行处理,上面的t->t.name中的t是Stream<T>的泛型,而这个T又是List<T>中的泛型,t可以换成其他任何字母,并且也可以点出User类的相关方法,并且还可以支持复合筛选,比如我们要筛选姓韩的女生,可以这样写
结果:耗时281[{"age":"22", "name":"韩天琪", "password":"f123456", "gendar":"2", "hasMarried":"false"} ]
也可以这样写
耗时296ms还可以改变条件的顺序:
耗时265ms场景四:只列出所有人的名字和婚姻状况
这次要用的.map()函数,map()就是为了只显示对象的一部分信息而准备的。
传统方式:
耗时:0[王旭:已婚
, 王旭:已婚
, 王旭:已婚
, 孙萍:未婚
, 步传宇:未婚
, 蔡明浩:已婚
, 郭林杰:未婚
, 韩凯:已婚
, 韩天琪:未婚
, 郝玮:未婚
, 胡亚强:未婚
, 季恺:未婚
, 荆帅:已婚
, 姜有琪:未婚
]
java8方式:
结果相同:耗时234
场景五:判断当前数组是否包含某些特定元素
如果我要看看现在的用户中是否有未成年人怎么办呢
传统方法:
结果:耗时0 trueJava8方法:
耗时78ms 结果相同场景六:确认所有元素均满足某一条件
这里以查看所有人是否都已婚为例
传统方法:
结果:耗时0 false
java8方法:
结果相同,耗时46ms场景七:求和求平均值
求和这种操作在用户管理上十分频繁,java8的流操作省去了循环,节省了大量代码,比如我们要求所有用户的平均年龄
传统方法:
结果:耗时0 平均年龄18java8方法:
这里先用map方法把所有元素的age取出来,然后调用Integer.sum方法进行聚合(reduce函数),得到年龄和,返回是一个OptionalInt对象,这里面包含一个int,但也有可能为null,注意这里reduce()函数的参数是一个方法,注意Java8支持将函数作为参数传入了,有点像c++写法,规则是完整类名::方法名(方法参数...)
结果相同,耗时63ms场景八:分组
比如我们要按用户的年龄进行分组,相同年龄的人分在同一组,用一个Map<Integer,List<User>>存放,key是年龄,value是该年龄的所有用户
传统方法:
结果:
耗时0
{16=[{"age":"16", "name":"姜有琪", "password":"k123456", "gendar":"1", "hasMarried":"false"}
], 17=[{"age":"17", "name":"郭林杰", "password":"d123456", "gendar":"1", "hasMarried":"false"}
, {"age":"17", "name":"荆帅", "password":"j123456", "gendar":"1", "hasMarried":"true"}
], 18=[{"age":"18", "name":"蔡明浩", "password":"c123456", "gendar":"1", "hasMarried":"true"}
], 19=[{"age":"19", "name":"胡亚强", "password":"h123456", "gendar":"1", "hasMarried":"false"}
], 21=[{"age":"21", "name":"孙萍", "password":"a123456", "gendar":"2", "hasMarried":"false"}
, {"age":"21", "name":"郝玮", "password":"g123456", "gendar":"2", "hasMarried":"false"}
], 5=[{"age":"5", "name":"韩凯", "password":"e123456", "gendar":"1", "hasMarried":"true"}
], 22=[{"age":"22", "name":"王旭", "password":"123456", "gendar":"1", "hasMarried":"true"}
, {"age":"22", "name":"王旭", "password":"123456", "gendar":"1", "hasMarried":"true"}
, {"age":"22", "name":"王旭", "password":"123456", "gendar":"1", "hasMarried":"true"}
, {"age":"22", "name":"韩天琪", "password":"f123456", "gendar":"2", "hasMarried":"false"}
], 23=[{"age":"23", "name":"步传宇", "password":"b123456", "gendar":"1", "hasMarried":"false"}
], 14=[{"age":"14", "name":"季恺", "password":"i123456", "gendar":"1", "hasMarried":"false"}
]}
如果想按是否结婚分组,也就是key变成bool,那就应该这么写
耗时也是62ms场景九:链式操作
如果我们需要打印所有女生的名字,那么同样可以一行代码搞定,思路是先通过源Stream通过筛选得到一个新Stream,再对这个新的Stream进行操作,如此循环,注意这里使用的forEach()函数是遍历Stream中的每一个元素,参数是方法,注意Java8支持将函数作为参数传入了,有点像c++写法,规则是完整类名::方法名(方法参数...)
结果:孙萍韩天琪
郝玮
耗时47
- Java8 Stream流操作
- java8 Stream流操作介绍
- 【JAVA8】stream 流相关操作
- Java8 常用的Stream流操作
- Java8 Stream操作
- java8 stream 操作
- Java8的Stream操作
- Java8 Stream 基本操作示例
- Java8集合及Stream操作
- Java8 stream流介绍
- Java8-Stream流处理
- java8 stream流 collect
- Java8 Stream流操作在用户系统中的妙用
- Java8系列--Java Stream入门篇(流的操作)
- Java8系列--Java Stream进阶篇(流的操作)
- java8 Stream API各种流操作应用(2)
- java8新概念之stream流
- Java8新特性Stream流
- 第三章 Django基础知识回顾
- 同时使用clipboard和layer时遇到的坑
- Intellij IDEA 2017.3注册server
- Android View 基础知识
- c#从入门到精通最全笔记——基础理论篇
- Java8 Stream流操作
- 在Linux系统的命令行中为MySQL创建用户的方法
- deepin下安装texlive2017+Visual Studio Code搭建latex编写环境
- maven 自定义命令笔记
- spirng配置
- 快速搭建一个Express工程骨架
- Java生成验证码图片并进行验证
- 名字排序,大小排序
- linux-centos如何配置mongodb