Java8采用stream、parallelStream迭代的区别
Java8采用stream、parallelStream迭代的区别
我们都知道在Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
通过查看API能够看到Java8 API为我们提供了Stream和parallelStream两个不同的方法,那么同样是流处理,这两个方法又有什么区别呢?首先我们来看看以下的代码:
public static void main(String[] args) {
List<Integer> numberList = Arrays.asList(1,2,3,4,5,6,7,8,9);
System.out.println("运行结果:");
// stream method
numberList.stream().forEach(number -> {
System.out.print(String.format("%d ",number));
});
System.out.println("\r");
// parallelStream method
numberList.parallelStream().forEach(number -> {
System.out.print(String.format("%d ",number));
});
System.out.println("\r");
// parallelStream method
numberList.parallelStream().forEachOrdered(number -> {
System.out.print(String.format("%d ",number));
});
System.out.println("\r");
}
通过多次运行上述代码,我们可以发现,通过parallelStream方法迭代集合,每次输出的结果都不一样,而通过steam方法或parallelStream方法并以forEachOrdered方式,每次执行输出的结果都是一样的,并且顺序符合集合元素的存放顺序。
那么,为什么会造成这样的结果差异呢,难道parallelStram是采用多线程并行的方式运行?于是,我们进一步修改下我们的代码来验证一下猜测。
public static void main(String[] args) {
System.out.println("运行结果:");
List<Integer> numberList = Arrays.asList(1,2,3,4,5,6,7,8,9);
// stream method
numberList.stream().forEach(number -> {
System.out.println(String.format("Stream The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));
});
System.out.println("\r");
// parallelStream method
numberList.parallelStream().forEach(number -> {
System.out.println(String.format("ParallelStream The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));
});
System.out.println("\r");
// parallelStream method
numberList.parallelStream().forEachOrdered(number -> {
System.out.println(String.format("ParallelStream forEach Ordered The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));
});
System.out.println("\r");
}
修改后代码运行结果如下:
运行结果:
Stream The Current Thread's ID is 1 and output number 1
Stream The Current Thread's ID is 1 and output number 2
Stream The Current Thread's ID is 1 and output number 3
Stream The Current Thread's ID is 1 and output number 4
Stream The Current Thread's ID is 1 and output number 5
Stream The Current Thread's ID is 1 and output number 6
Stream The Current Thread's ID is 1 and output number 7
Stream The Current Thread's ID is 1 and output number 8
Stream The Current Thread's ID is 1 and output number 9
ParallelStream The Current Thread's ID is 1 and output number 6
ParallelStream The Current Thread's ID is 19 and output number 9
ParallelStream The Current Thread's ID is 18 and output number 1
ParallelStream The Current Thread's ID is 15 and output number 2
ParallelStream The Current Thread's ID is 17 and output number 4
ParallelStream The Current Thread's ID is 14 and output number 8
ParallelStream The Current Thread's ID is 13 and output number 3
ParallelStream The Current Thread's ID is 16 and output number 7
ParallelStream The Current Thread's ID is 1 and output number 5
ParallelStream forEach Ordered The Current Thread's ID is 15 and output number 1
ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 2
ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 3
ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 4
ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 5
ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 6
ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 7
ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 8
ParallelStream forEach Ordered The Current Thread's ID is 14 and output number 9
Disconnected from the target VM, address: '127.0.0.1:52976', transport: 'socket'
Process finished with exit code 0
通过上面的运行结果,我们可以看到通过ParallelStream方法迭代的方法,是采用多线程的,可以看过每次输出都是不同的线程ID,而ParallelStream(). forEach Ordered是在多线程的基础上,保证了数据的顺序输出。到此,我们验证了我们的猜测ParallelStream方法是多线程的,而关于线程是否并行的验证,我们需进一步修改下我们的代码,于是有了下面的代码:
public static void main(String[] args) throws InterruptedException {
System.out.println("运行结果:");
List<Integer> numberList = Arrays.asList(1,2,3,4,5,6,7,8,9);
//for
Long forBegin = System.currentTimeMillis();
for(Integer number : numberList){
//System.out.println(String.format("For The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));
Thread.sleep(1000);
}
System.out.println(String.format("For execute time cost %d ms",System.currentTimeMillis()-forBegin));
System.out.println("\r");
// stream method
Long streamBegin = System.currentTimeMillis();
numberList.stream().forEach(number -> {
//System.out.println(String.format("Stream The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println(String.format("Stream execute time cost %d ms",System.currentTimeMillis()-streamBegin));
System.out.println("\r");
// parallelStream method
Long parallelStreamBegin = System.currentTimeMillis();
numberList.parallelStream().forEach(number -> {
//System.out.println(String.format("ParallelStream The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println(String.format("ParallelStream execute time cost %d ms",System.currentTimeMillis()-parallelStreamBegin));
System.out.println("\r");
// parallelStream method
Long parallelStreamForEachOrderBegin = System.currentTimeMillis();
numberList.parallelStream().forEachOrdered(number -> {
//System.out.println(String.format("ParallelStream forEachOrdered The Current Thread's ID is %d and output number %d ",Thread.currentThread().getId(),number));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println(String.format("ParallelStream forEachOrdered execute time cost %d ms",System.currentTimeMillis()-parallelStreamForEachOrderBegin));
System.out.println("\r");
}
这里我们加入了传统的for循环迭代方式,加入一起比较,由于要体现多线程并行的优势,这里我们将每次循环里加入线程休眠1秒钟,运行后的结果如下:
运行结果:
For execute time cost 9032 ms
Stream execute time cost 9079 ms
ParallelStream execute time cost 2011 ms
ParallelStream forEachOrdered execute time cost 9037 ms
通过运行结果,我们可以看到parallelStream().forEach方式耗时最短,而另外其他3种方式运行的耗时都几乎接近。因此,我们可以断定我们的猜测是正确的,parallelStream().forEach是通过多线程并行的方式来执行我们的代码,而parallelStream(). forEachOrdered也是采用多线程,但由于加入了顺序执行约束,故程序是采用多线程同步的方式运行的,最终耗时与for、stream两种单线程执行的耗时接近,但parallelStream(). forEachOrdered由于是多线程,与for、stream两种单线程的方式相比,优势在于很好的利用了CPU多核的资源。感兴趣的同学可以通过以下代码查看CPU的核数,并通过jstack dump出堆栈来查看线程对CPU使用的情况。
System.out.println("系统一共有"+Runtime.getRuntime().availableProcessors()+"个cpu");
来源:Java8采用stream、parallelStream迭代的区别 - 你我一路随行 - 博客园
Java8采用stream、parallelStream迭代的区别相关推荐
- 【Java8新特性】关于Java8的Stream API,看这一篇就够了!!
写在前面 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*) ,那什么是Stream API呢?Java8中 ...
- 一文带你了解Java8之Stream
Java8 Stream流式编程 简介 Java8中stream是用于对集合迭代器的增强,使之能供完成更高效的聚合操作(例如过滤.排序.统计分组等)或者大批量数据操作.此外,stream与lambda ...
- Java8的 Stream 流的各种用法
Java8 的 Stream 流的各种用法 什么是Stream 1. Stream可以由数组或集合创建,对流的操作分为两种 2. Stream的特性 3. Stream可以通过集合数组创建 4. st ...
- Java8特性 stream流常用方法
Java8特性 stream流常用方法 Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据. Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方 ...
- 玩转Java8的 Stream 之函数式接口
作者:litesky www.jianshu.com/p/2338cabc59e1 函数式接口是伴随着Stream的诞生而出现的,Java8Stream 作为函数式编程的一种具体实现,开发者无需关注怎 ...
- Java8种Stream流相关操作——集合的筛选、归约、分组、聚合
过滤.筛选 filter skip /*** 过滤 筛选*/@Testpublic void test2(){List<String> list = Arrays.asList(&qu ...
- Java8的Stream API使用(笔记)
个人转载仅作为笔记使用,如有任何问题可以到原文链接探讨,原文连接为:https://www.cnblogs.com/jimoer/p/10995574.html 前言 这次想介绍一下Java Stre ...
- Java8的Stream API使用
前言 这次想介绍一下Java Stream的API使用,最近在做一个新的项目,然后终于可以从老项目的祖传代码坑里跳出来了.项目用公司自己的框架搭建完成后,我就想着把JDK版本也升级一下吧(之前的项目, ...
- stream和迭代器的区别
什么是迭代器? 迭代器,提供一种访问一个集合对象各个元素的途径,同时又不需要暴露该对象的内部细节.java通过提供Iterator和Iterable俩个接口来实现集合类的可迭代性,迭代器主要的用法是: ...
最新文章
- C++11 unordered_map详细介绍
- oracle idm suite,CorelDRAW Graphics Suite 2018官方英文试用版 离线直接安装 下载地址
- ICLR 2020 开源论文 | 隐空间的图神经网络:Geom-GCN
- 奇舞团的博客(360前端团队)
- lucene 查询示例_高级Lucene查询示例
- 血红蛋白判断access程序答案_普渡大学开发智能手机应用程序 帮助评估贫血症情况...
- C#文件流传输[类似于QQ][引]
- Chrome控制台console的各种用法(方便调试)
- Apache Ant 安装教程
- java计算机毕业设计化妆品销售网站MyBatis+系统+LW文档+源码+调试部署
- 计算机启动到安全模式,电脑正常开机会进入安全模式怎么办
- 射灯安装方法图解_射灯如何安装—射灯的安装方法介绍
- c语言while(*p *q),C语言经典例题和答案
- android发短信!渣本毕业两年经验,终局之战
- Python实现相空间重构求关联维数——GP算法、自相关法求时间延迟tau、最近邻算法求嵌入维数m
- Nand2Tetris - Week 1
- 丰田增设电池生产线,加快丰田电动化进程
- 煮咖啡的动态页面演示动画
- 环境变量是个啥? 没有勾选Add to Path怎么办?
- linux C语言TCP协议实现镜像服务器,并发服务器,文件传输
热门文章
- QT的QWriteLocker类的使用
- html fmt转换日期格式,js通用时间格式转换函数
- 鸿蒙系统是单任务还是多任务,在鸿蒙系统上使用MQTT编程
- 使用opencv读取图片错误([ WARN:0@13.701] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\..)
- Azkaban实战,Command类型单一job示例,任务中执行外部shell脚本,Command类型多job工作flow,HDFS操作任务,MapReduce任务,HIVE任务
- 6.set ff=unix;设置Linux中文件中每行后又尖括号的情况
- Oracle_Net_Configuration_Assistant_配置步骤
- 因为虚拟机导致的错误
- Android中contentProvider的用途
- php网站适合优化_php开发大型网站如何优化的方案详解