首先先说明,这篇文章的对比有失公允,stream()和parallelStream()差距还是挺大的,用parallelStream()这种开线程的玩意和单线程比较,有点不公平。
Stream流是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值),它只是在原数据集上定义了一组操作。
Stream流不保存数据,Stream操作是尽可能惰性的,即每当访问到流中的一个元素,才会在此元素上执行这一系列操作。
Stream流也不会改变原有数据。
具体Stream流的知识请大家自行搜索,仅仅以循环效率来考虑,确实有点一叶障目。
以下内容大家看看就好:
————————————————————————————————————————————
java8新出的循环方式,在网上有大量的道友说用流的方式效率反而更低了。
大量的结论表明,这种方式只是语法糖(for-forEach-stream三种遍历方法执行效率比较与选用思考 - ZZY1078689276的专栏 - CSDN博客
https://blog.csdn.net/ZZY1078689276/article/details/79430772)这篇文章一样的内容看了不止一次,我都不知道谁先写的。。
不过,耳听为虚,眼见为实,上代码亲自试验:
public static void main(String[] args) { // 测试源 List<String> sourceList = new ArrayList<>(); for (int i = 0;i<10;i++) { sourceList.add("第" + i + "条数据"); } System.out.println("数据条数:" + sourceList.size()); long a1=System.currentTimeMillis(); for (int i = 0;i < sourceList.size();i++) doSome(); long a2=System.currentTimeMillis(); System.out.println("普通for循环用时:" + (a2-a1)); long b1=System.currentTimeMillis(); for (String t:sourceList) doSome(); long b2=System.currentTimeMillis(); System.out.println("增强for循环用时:" + (b2-b1)); long c1=System.currentTimeMillis(); sourceList.forEach((t)-> doSome()); long c2=System.currentTimeMillis(); System.out.println("forEach循环用时:" + (c2-c1)); long d1=System.currentTimeMillis(); sourceList.parallelStream().forEach((t)-> doSome()); long d2=System.currentTimeMillis(); System.out.println("forEach-Stream循环用时:" + (d2-d1)); }
结果如下:
数据条数:10
普通for循环用时:0
增强for循环用时:0
forEach循环用时:43
forEach-Stream循环用时:6
好吧,数据少了点,不过结果也很明显了,使用forEach循环耗时最多,流启动也很耗时。
不过,让我们把循环次数提升至100W如何?
数据条数:1000000
普通for循环用时:3
增强for循环用时:10
forEach循环用时:46
forEach-Stream循环用时:33
forEach-Stream方式用时增加了,不过forEach用时并没有明显增加,再来一次:
数据条数:1000000
普通for循环用时:3
增强for循环用时:7
forEach循环用时:38
forEach-Stream循环用时:31
exm?forEach循环用时反而减少了是什么情况?不过今天我不研究原理,只看结论的话,for循环和增强for循环至少还是比新出的forEach-Stream要强很多的。
但这么一来,难道新功能真的只是语法糖么?
有人问我doSome()做了什么?实际上我什么都没做,但如果我真的做了什么呢?
比如等待一毫秒?
private static void doSome() { try { Thread.sleep(1); } catch (Exception e) { e.printStackTrace(); } }
再来一次:
数据条数:10000
普通for循环用时:10025
增强for循环用时:10009
forEach循环用时:10067
forEach-Stream循环用时:1567
Duang!!!!!!!
forEach-Stream的效率获得了碾压式的胜利!有人说是因为jvm预热原因,但先且不论预热的是什么(通常是指启动时加载的东西),预热这种一次性的行为怎么可能取得这么大的提升?
于是,让我们打印一下doSome()的线程
ForkJoinPool.commonPool-worker-5
ForkJoinPool.commonPool-worker-4
ForkJoinPool.commonPool-worker-6
ForkJoinPool.commonPool-worker-2
main
ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-7
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-6
main
ForkJoinPool.commonPool-worker-2
ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-4
ForkJoinPool.commonPool-worker-5
ForkJoinPool.commonPool-worker-7
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-5
main
So,还用我解释什么么?
stream().forEach用的多线程方式,其调用线程池的时候必然会耗费更多的时间。但如果你在循环内要处理的事情很多,或者要循环调用远程接口/数据库的时候,无疑极大的提升了效率
恭喜你学会了最简洁的多线程编程!