作者:funnyZpC
出处:cnblogs.com/funnyzpc/p/10382053.html

一. Stream(流)是什么,干什么

Stream是一类用于替代对集合操作的工具类+Lambda式编程,他可以替代现有的遍历、过滤、求和、求最值、排序、转换等

二. Stream操作方式

  • 并行方式parallelStream

  • 顺序方式Stream

三. Stream优势

  • Lambda 可有效减少冗余代码,减少开发工作量

  • 内置对集合List、Map的多种操作方式,含基本数据类型处理

  • 并行Stream有效率优势(内置多线程)

四. Stream(流)的基本使用

  • 遍历forEach

@Test
public void stream() {//操作ListList<Map<String, String>> mapList = new ArrayList() {{Map<String, String> m = new HashMap();m.put("a", "1");Map<String, String> m2 = new HashMap();m2.put("b", "2");add(m);add(m2);}};mapList.stream().forEach(item-> System.out.println(item));//操作MapMap<String,Object> mp = new HashMap(){{put("a","1");put("b","2");put("c","3");put("d","4");}};mp.keySet().stream().forEachOrdered(item-> System.out.println(mp.get(item)));
}
  • 过滤filter

List<Integer> mapList = new ArrayList() {
{add(1);add(10);add(12);add(33);add(99);
}
};
//mapList.stream().forEach(item-> System.out.println(item));
mapList = mapList.stream().filter(item->{
return item>30;
}).collect(Collectors.toList());
System.out.println(mapList);
  • 转换map和极值

@Test
public void trans(){List<Person> ps = new ArrayList<Person>(){{Person p1 = new Person();p1.setAge(11);p1.setName("张强");Person p2 = new Person();p2.setAge(17);p2.setName("李思");Person p3 = new Person();p3.setAge(20);p3.setName("John");add(p1);add(p2);add(p3);}};//取出所有age字段为一个ListList<Integer> sumAge = ps.stream().map(Person::getAge).collect(Collectors.toList());System.out.println(sumAge);//取出age最大的那Integer maxAge =sumAge.stream().max(Integer::compare).get();System.out.println(maxAge);
}class Person{private String name;private Integer age;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}

五. Stream(流)的效率+ 模拟非耗时简单业务逻辑

class Person{private String name;private int age;private Date joinDate;private String label;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Date getJoinDate() {return joinDate;}public void setJoinDate(Date joinDate) {this.joinDate = joinDate;}public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}
}
public class DataLoopTest {private static final Logger LOG= LoggerFactory.getLogger(DataLoopTest.class);private static final List<Person> persons = new ArrayList<>();static {for(int i=0;i<=1000000;i++){Person p = new Person();p.setAge(i);p.setName("zhangSan");p.setJoinDate(new Date());persons.add(p);}}/*** for 循环耗时 ===> 1.988* for 循环耗时 ===> 2.198* for 循环耗时 ===> 1.978**/@Testpublic void forTest(){Instant date_start = Instant.now();int personSize = persons.size();for(int i=0;i<personSize;i++){persons.get(i).setLabel(persons.get(i).getName().concat("-"+persons.get(i).getAge()).concat("-"+persons.get(i).getJoinDate().getTime()));}Instant date_end = Instant.now();LOG.info("for 循环耗时 ===> {}", Duration.between(date_start,date_end).toMillis()/1000.0);}/***  forEach 循环耗时 ===> 1.607*  forEach 循环耗时 ===> 2.242*  forEach 循环耗时 ===> 1.875*/@Testpublic void forEach(){Instant date_start = Instant.now();for(Person p:persons){p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime()));}Instant date_end = Instant.now();LOG.info("forEach 循环耗时 ===> {}", Duration.between(date_start,date_end).toMillis()/1000.0);}/***  streamForeach 循环耗时 ===> 1.972*  streamForeach 循环耗时 ===> 1.969*  streamForeach 循环耗时 ===> 2.125*/@Testpublic void streamForeach(){Instant date_start = Instant.now();persons.stream().forEach(p->p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime())));Instant date_end = Instant.now();LOG.info("streamForeach 循环耗时 ===> {}", Duration.between(date_start,date_end).toMillis()/1000.0);}/***  parallelStreamForeach 循环耗时 ===> 1.897*  parallelStreamForeach 循环耗时 ===> 1.942*  parallelStreamForeach 循环耗时 ===> 1.642*/@Testpublic void parallelStreamForeach(){Instant date_start = Instant.now();persons.parallelStream().forEach(p->p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime())));Instant date_end = Instant.now();LOG.info("parallelStreamForeach 循环耗时 ===> {}", Duration.between(date_start,date_end).toMillis()/1000.0);}}
  • 模拟耗时简单业务逻辑

public class DataLoopBlockTest {private static final Logger LOG= LoggerFactory.getLogger(DataLoopTest.class);private static final List<Person> persons = new ArrayList<>();static {for(int i=0;i<=100000;i++){Person p = new Person();p.setAge(i);p.setName("zhangSan");p.setJoinDate(new Date());persons.add(p);}}/*** for 循环耗时 ===> 101.385* for 循环耗时 ===> 102.161* for 循环耗时 ===> 101.472**/@Testpublic void forTest(){Instant date_start = Instant.now();int personSize = persons.size();for(int i=0;i<personSize;i++){try {Thread.sleep(1);persons.get(i).setLabel(persons.get(i).getName().concat("-"+persons.get(i).getAge()).concat("-"+persons.get(i).getJoinDate().getTime()));}catch (Exception e){e.printStackTrace();}}Instant date_end = Instant.now();LOG.info("for 循环耗时 ===> {}", Duration.between(date_start,date_end).toMillis()/1000.0);}/***  forEach 循环耗时 ===> 101.027*  forEach 循环耗时 ===> 102.488*  forEach 循环耗时 ===> 101.608*/@Testpublic void forEach(){Instant date_start = Instant.now();for(Person p:persons){try {Thread.sleep(1);p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime()));}catch (Exception e){e.printStackTrace();}}Instant date_end = Instant.now();LOG.info("forEach 循环耗时 ===> {}", Duration.between(date_start,date_end).toMillis()/1000.0);}/***  streamForeach 循环耗时 ===> 103.246*  streamForeach 循环耗时 ===> 101.128*  streamForeach 循环耗时 ===> 102.615*/@Testpublic void streamForeach(){Instant date_start = Instant.now();//persons.stream().forEach(p->p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime())));persons.stream().forEach(p->{try {Thread.sleep(1);p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime()));}catch (Exception e){e.printStackTrace();}});Instant date_end = Instant.now();LOG.info("streamForeach 循环耗时 ===> {}", Duration.between(date_start,date_end).toMillis()/1000.0);}/***  parallelStreamForeach 循环耗时 ===> 51.391*  parallelStreamForeach 循环耗时 ===> 53.509*  parallelStreamForeach 循环耗时 ===> 50.831*/@Testpublic void parallelStreamForeach(){Instant date_start = Instant.now();//persons.parallelStream().forEach(p->p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime())));persons.parallelStream().forEach(p->{try {Thread.sleep(1);p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime()));}catch (Exception e){e.printStackTrace();}});Instant date_end = Instant.now();LOG.info("parallelStreamForeach 循环耗时 ===> {}", Duration.between(date_start,date_end).toMillis()/1000.0);//LOG.info("\r\n===> {}",JSON.toJSONString(persons.get(10000)));}}

可以看到在百万数据下做简单数据循环处理,对于普通for(for\foreach)循环或Stream(并行、非并行)下,几者的效率差异并不明显。

注意: 在百万数据下,普通for、foreach循环处理可能比Stream的方式快许多,对于这点效率的损耗,其实lambda表达式对代码的简化更大!

另外,在并行流的循环下速度提升了一倍之多,当单个循环耗时较多时,会拉大与前几者的循环效率  (以上测试仅对于循环而言,其他类型业务处理,比如排序、求和、最大值等未做测试,个人猜测与以上测试结果相似)

六. Stream(流)注意项

  • 并行Stream不是线程安全的,当对循坏外部统一对象进行读写时候会造成意想不到的错误,这需要留意

  • 因Stream总是惰性的,原对象是不可以被修改的,在集合处理完成后需要将处理结果放入一个新的集合容器内

  • 普通循环与Stream(非并行)循环,在处理处理数据量比较大的时候效率是一致的,推荐使用Stream的形式

  • 对于List删除操作,目前只提供了removeIf方法来实现,并不能使用并行方式

  • 对于lambda表达式的写法

  • 当表达式内只有一个返回boolean类型的语句时候语句是可以简写的,例如:

persons.parallelStream().forEach(p->p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime())));
  • 当表达式内会有一些复杂处理逻辑时需要加上大括号,这与初始化List参数方式大致一致

try {Thread.sleep(1);p.setLabel(p.getName().concat("-"+p.getAge()).concat("-"+p.getJoinDate().getTime()));}catch (Exception e){e.printStackTrace();}
});

七. stream&Lambda表达式常用api方法

  • 流到流之间的转换类

    • filter(过滤)

    • map(映射转换)

    • mapTo[Int|Long|Double] (到基本类型流的转换)

    • flatMap(流展开合并)

    • flatMapTo[Int|Long|Double]

    • sorted(排序)

    • distinct(不重复值)

    • peek(执行某种操作,流不变,可用于调试)

    • limit(限制到指定元素数量)

    • skip(跳过若干元素)

  • 流到终值的转换类

    • toArray(转为数组)

    • reduce(推导结果)

    • collect(聚合结果)

    • min(最小值)

    • max(最大值)

    • count (元素个数)

    • anyMatch (任一匹配)

    • allMatch(所有都匹配)

    • noneMatch(一个都不匹配)

    • findFirst(选择首元素)

    • findAny(任选一元素)

  • 直接遍历类

    • forEach (不保证顺序遍历,比如并行流)

    • forEachOrdered(顺序遍历)

  • 构造流类

    • empty (构造空流)

    • of (单个元素的流及多元素顺序流)

    • iterate (无限长度的有序顺序流)

    • generate (将数据提供器转换成无限非有序的顺序流)

    • concat (流的连接)

    • Builder (用于构造流的Builder对象)

关微信公众号:互联网架构师,在后台回复:2T,可以获取我整理的教程,都是干货。

猜你喜欢

1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBook发起和总结

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别

9、2T架构师学习资料干货分享

Java 8 Stream 闪亮登场!相关推荐

  1. JAVA版本微信管家平台—JeeWx 捷微 4.1 微服务版本发布,微信砍价活动闪亮登场!...

    捷微 4.1   微服务版本发布,微信砍价活动闪亮登场 ^_^ JEEWX 从4.0版本开始,技术架构全新换代更名 "捷微H5".这是一款开源免费的微信运营平台,是jeewx的新一 ...

  2. java 西部数码_实力打造 西部数码JAVA虚拟主机重装登场

    核心提示:近期,西部数码全新打造的JAVA虚拟主机重装闪亮登场,Java虚拟主机采用CentOs5.1/APACHE2.0/ TOMCAT5.5架构,用户可以独享jvm和tomcat服务,并可自主重新 ...

  3. 牛逼哄洪的 Java 8 Stream,性能也牛逼么?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 Java8的Stream API可以极大提高Java程序员的生产力 ...

  4. java8 group by_java8新特性Java 8 – Stream Collectors groupingBy 示例 - Java教程

    在这篇教程中,将向你展示如何使用Java 8 Stream的Collectors,来对一个List进行分组,计算个数,求和以及排序. 1. Group By, Count and Sort 1.1 对 ...

  5. 从Java 8中的java.util.stream.Stream检索列表

    本文翻译自:Retrieving a List from a java.util.stream.Stream in Java 8 I was playing around with Java 8 la ...

  6. Java 8 Stream Api 中的 skip 和 limit 操作

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 1. 前言 Java 8 Stream API 中的sk ...

  7. 计算机合成生物学博士,重磅!Tim Lu 出任 CEO,合成生物学新锐今日闪亮登场

    原标题:重磅!Tim Lu 出任 CEO,合成生物学新锐今日闪亮登场 今日,业内传来一条引入关注的新闻--位于南旧金山的合成生物学新锐 Senti Biosciences 闪亮登场,获得了 5300 ...

  8. Java 8 Stream API详解--转

    原文地址:http://blog.csdn.net/chszs/article/details/47038607 Java 8 Stream API详解 一.Stream API介绍 Java 8引入 ...

  9. Java 8 Stream Tutorial--转

    原文地址:http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ This example-driven tutori ...

  10. Java 8 - Stream实战

    文章目录 Pre 练习 基础数据 (1) 找出2011年发生的所有交易,并按交易额排序(从低到高) (2) 交易员都在哪些不同的城市工作过? (3) 查找所有来自于剑桥的交易员,并按姓名排序. (4) ...

最新文章

  1. 吴恩达最新成果 CheXNet详解:肺炎诊断准确率超专业医师
  2. POJ_3685_Matrix_(二分,查找第k大的值)
  3. Spark基本操作SparkSession,DatasetRow,JavaRDDRow
  4. 【计算机网络】wireshark数据流追踪、图像抓取(转)
  5. CF245H Queries for Number of Palindromes
  6. Spring : spring基于xml配置Bean
  7. python重命名csv文件_Python根据文件中选定的字符复制和重命名许多小csv文件
  8. 从入门到入土:Python爬虫学习|实例练手|爬取百度产品列表|Xpath定位标签爬取|代码注释详解
  9. 讨论生活中什么样东西可以何种变量描述找出生活中顺序执行事情用c语言,《C语言程序设计》实验指导书...
  10. vue组件,通过props父组件给子组件传值,WTF, 子组件报错undefined???
  11. H5小游戏源码/王了个王消消乐游戏源码带后台
  12. 23种设计模式总结+清晰图解(必收藏)
  13. 千兆网线做法和网线接法注意事项
  14. 提取网页内容-Python
  15. 虚幻4引擎开发的手游_2019虚幻4手游大作排行-虚幻引擎开发的手机游戏
  16. D碳社区周报:上海市:推进崇明世界级生态岛碳中和示范区建设,院士专家在论坛上提出建议
  17. canvas画布中实现气泡
  18. 非法本法硕最真实的就业现状
  19. Windows运行vbs在微信下自动发送烟花、庆祝
  20. 解决React Native安装应用到真机(红米3S)报Execution failed for task ':app:installDebug'的错误...

热门文章

  1. 端口占用问题解决办法(以1099端口为例)
  2. 为什么Docker不能解决云上的所有问题
  3. Delphi中Sender对象的定义
  4. “云计算之旅”筹备完成,意见征询!
  5. 苹果Mac测试及维护工具:​​​​​​​​Techtool Pro
  6. iOS的帮助网站(企业包发布)adhoc的测试
  7. JProfiler 12 for Mac(Java开发分析工具)
  8. Default Folder X 5 for Mac(文件快捷访问工具)
  9. 如果Mac无法连接到其他电脑共享怎么办?
  10. 如何在Mac上快速签署PDF