项目记事【StreamAPI】:使用 StreamAPI 简化对 Collection 的操作
最近项目里有这么一段代码,我在做 code-review 的时候,觉得可以使用 Java8 StreamAPI 简化一下。
这里先看一下代码(不是源码,一些敏感信息被我用其他类替代了):
private static Set<String> doSomething1(String input) {
Set<String> target = new HashSet<>();
if (input != null) {
for (Pojo pojo : source) {
if (input.equals(pojo.getStr1())) {
target.add(pojo.getStr2());
}
}
}
return target;
}
其中 source 是一个 Set<Pojo> 的共享变量,Pojo 是自定义对象:
private static class Pojo {
String str1;
String str2;
Pojo(String str1, String str2) {
this.str1 = str1;
this.str2 = str2;
}
public String getStr1() {
return str1;
}
public String getStr2() {
return str2;
}
}
这个 doSomething1() 方法的功能很简单:
- 声明一个新的 Set<String> 结构 target。
- 遍历 source。
- 将 input 依次与 source 中每个元素的 str1 属性进行比对。
- 若比对成功,将元素的 str2 属性加入 target。
- 遍历结束,返回 target。
从单纯的 Coding 角度而言,doSomething1() 方法实现得已经足够简便,但是使用 Java8 StreamAPI 可以仅仅使用一行代码的情况下完成这些操作。
仔细分析以上的操作,可以归纳为三个步骤:
- 过滤数据 -> input.equals(pojo.getStr1()
- 提取数据 -> pojo.getStr2()
- 收集数据 -> target.add(pojo.getStr2())
这三个操作分别对应了 StreamAPI 的 filter,map,collect,因此可以简化成这样:
private static Set<String> doSomething2(String input) {
return source.stream().filter(pojo -> input.equals(pojo.getStr1())).map(Pojo::getStr2).collect(Collectors.toSet());
}
功能测试
private static Set<Pojo> source = new HashSet<>();
public static void main(String[] args) {
prepareData();
for (String s : doSomething1("1")) {
System.out.println(s);
}
for (String s : doSomething2("1")) {
System.out.println(s);
}
}
private static void prepareData() {
Pojo pojo1 = new Pojo("1", "2");
Pojo pojo2 = new Pojo("3", "4");
source.add(pojo1);
source.add(pojo2);
}
输出如下:

发现两者是等价的。
性能测试
一个应用程序的优秀与否,不在于代码的漂亮程度,而在于性能。
public static void main(String[] args) {
prepareData();
long t3 = System.nanoTime();
doSomething2("123441");
long t4 = System.nanoTime();
printTime(t3, t4);
long t1 = System.nanoTime();
doSomething1("123441");
long t2 = System.nanoTime();
printTime(t1, t2);
}
private static void printTime(long t1, long t2) {
long t = t2 - t1;
double factor = Math.pow(10, 9);
System.out.println(t / factor);
}
private static void prepareData() {
final int scale = 100000000;
Random r = new Random();
for (int i = 0; i < scale; ++i) {
String str1 = r.nextInt(scale) + "";
String str2 = r.nextInt(scale) + "";
source.add(new Pojo(str1, str2));
}
}
测试结果:

可以发现,使用 StreamAPI 大大降低了程序的效率,当数据量足够大的时候,这个比例会不断缩小。
我们可以这样理解:StreamAPI 针对的是相对大数据的操作,为一个数据量较小的 Collection 起一个 Stream 非常得不偿失,有种大炮打蚊子的感觉。
最后的内存溢出,是在 prepareData 的时候,和处理数据没有关系。
最后贴上大神的测试:Java8 Lambda表达式和流操作如何让你的代码变慢5倍
所以流操作,慎用!
项目记事【StreamAPI】:使用 StreamAPI 简化对 Collection 的操作的更多相关文章
- java8-StreamAPI之collection归约操作
一说明 经过前一篇的StreamAPI学习,基本的流操作我相信大家都熟练于心了,那么今天是要详细解析一下收集器(collect)这么API 前提要区分,collect(StreamAPI)与coll ...
- 使用元数据简化jdbc代码---查询操作(用到反射)
使用元数据简化jdbc代码---查询操作(用到反射) 一 思路分析 简化就是把共同的地方提取出来并放到一个方法里,在用到时只要调用就ok了,上一篇介绍了更新的操作,而查询的操作相对来说比较复杂,因为 ...
- IDEA项目搭建七——使用Feign简化消费者端操作
一.简介 我们可以看到上一篇文章的消费者这边调用Service时比较麻烦,所以我们可以使用Feign来简化这部分操作,它底层也是使用Ribbon实现的只是Ribbon支持HTTP和TCP两种通信协议, ...
- IDEA项目搭建八——使用MybatisPlus简化数据库交互
一.MybatisPlus简化数据库交互 我们使用Mybatis发现需要在mapper.xml中写很多重复的简单CRUD(增删改查),使用MybatisPlus可以大大简化这部分代码,官方文档http ...
- 基于已构建S2SH项目配置全注解方式简化配置文件
如果还不熟悉s2sh项目搭建的朋友可以先阅读 eclipse环境下基于tomcat-7.0.82构建struts2项目 eclipse环境下基于已构建struts2项目整合spring+hiberna ...
- 项目记事【SpringMVC-1】:后台接收前端传来的JSON,并转成对象
背景: 最近项目中使用SpringMVC,需要从前端接收JSON格式的请求,在后端自动转成一个与JSON格式相同的对象. 由于是一个老项目,Spring的版本是3.2.7. 问题1:POST or G ...
- 项目记事【多线程】:关于 SimpledDateFormat 的多线程问题
背景: 最近项目引入了 SonarLink,解决代码规范的问题,在检查历史代码的时候,发现了一个问题. 先看代码: public class DateUtil { private static fin ...
- 项目记事【Hibernate-1】:调用 saveOrUpdate() 方法出错
Hibernate 版本:3.3.1 背景: 后端编辑一个对象,该对象(ProductDO)下,有一个另一个自定义对象(ProductLiabilityDO)的 OneToMany 关系,如下: @O ...
- 项目记事【SpringMVC-2】:将后台的对象,转成JSON报文
Spring版本:3.2.7 Jackson版本: <!--Jackson --> <dependency> <groupId>com.fasterxml.jack ...
随机推荐
- postman传递参数的问题
postman是一款通过post或者get发送请求测试代码的工具 如果是类的话,就选择JSON格式,如果是一个字段的方法,就直接写入方法值就好了比如 public PageResult<Info ...
- sparkSQL中udf的使用
在Spark中使用sql时一些功能需要自定义方法实现,这时候就可以使用UDF功能来实现 多参数支持 UDF不支持参数*的方式输入多个参数,例如String*,不过可以使用array来解决这个问题. 定 ...
- Problem G: 角谷步数
Problem G: 角谷步数 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 78 Solved: 28[Submit][Status][Web Bo ...
- vs2015“当前不会命中断点 还没有为该文档加载任何符号”的解决方法
解决方法:工具-选项-调试 -(启用“仅我的代码”)勾去掉
- red hat的防火墙怎么关闭
查看是否开启: service iptables status 关闭方法: service iptables stop 永远关闭: Ntsysv 把iptables前的*号去掉. 查看SELinux状 ...
- Activiti学习记录(五)
1.排他网关 说明: 1) 一个排他网关对应一个以上的顺序流 2) 由排他网关流出的顺序流都有个conditionExpression元素,在内部维护返回boolean类型的决策结果. 3) 决策网关 ...
- mui的选项卡js选中指定项
dom结构:在一定条件下想默认选中第二个选项卡 <div id="segmentedControl" class="mui-segmented-control mu ...
- 怎么选取训练神经网络时的Batch size?
怎么选取训练神经网络时的Batch size? - 知乎 https://www.zhihu.com/question/61607442 深度学习中的batch的大小对学习效果有何影响? - 知乎 h ...
- (转)CocoaPods
本文转自http://nshipster.cn/cocoapods/ 文明是建立在道路,桥梁,运河,下水道,管线,电线和光纤这些基础设施之上的.只要设计和施工得当,它们可以帮助社会成倍的发展. 唯一的 ...
- CCPC_1003
这个题可以暴力的哟,直接暴力的哟 不用做什么订立的哟 不需要特别判断的哟 去死吧!!!愚蠢的我! #include<bits/stdc++.h> using namespace std; ...