项目记事【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 ...
随机推荐
- UVA 1642 Magical GCD(gcd的性质,递推)
分析:对于区间[i,j],枚举j. 固定j以后,剩下的要比较M_gcd(k,j) = gcd(ak,...,aj)*(j-k+1)的大小, i≤k≤j. 此时M_gcd(k,j)可以看成一个二元组(g ...
- C语言中的异常处理机制
#define try if(!setjmp(Jump_Buffer)) 返回try现场后重新执行判断,所以有两次执行. http://blog.csdn.net/tian_dao_chou_qin/ ...
- CDQ分治入门
前言 \(CDQ\)分治是一个神奇的算法. 它有着广泛的用途,甚至在某些题目中还能取代\(KD-Tree\).树套树等恶心的数据结构成为正解,而且常数还小得多. 不过它也有一定的缺点,如必须离线操作, ...
- 【转】VS2010发布、打包安装程序(超全超详细)
1. 在vs2010 选择“新建项目”→“ 其他项目类型”→“ Visual Studio Installer→“安装项目”: 命名为:Setup1 . 这是在VS2010中将有三个文件夹, 1.“应 ...
- 【转】chrome浏览器的跨域设置——包括版本49前后两种设置
做前后分离的webapp开发的时候,出于一些原因往往需要将浏览器设置成支持跨域的模式,好在chrome浏览器就是支持可跨域的设置,网上也有很多chrome跨域设置教程.但是新版本的chrome浏览器提 ...
- http 调用错误处理
1. http code 在使用Nginx时,经常会碰到502 Bad Gateway和504 Gateway Time-out错误,下面以Nginx+PHP-FPM来分析下这两种常见错误的原因和解决 ...
- mysql基础,事物
- jquery 省市区联动插件
使用方式: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- float浮动布局(慕课网CSS笔记 + css核心技术详解第四章)
---------------------------------------------------------------------- CSS中的position: CSS三种布局方式: 标准流 ...
- 学习pytho第l六天 常用字符串用法
name='my name is dream' print(name.capitalize())#首字母大写 print(name.count(‘’a‘’))#判断字符串里有多少个a print(na ...