实现Java集合迭代的高性能
实现Java集合迭代的高性能
- 2018.7.14
- 版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。
一、介绍
Java开发者经常会遇到处理集合(比如ArrayList、HashSet)的情况,Java 8也提供了Lambda表达式和Streaming API来简化集合相关的工作。在大多数应用场景下,无需考虑集合迭代的性能消耗。但是,在一些极端情况下,比如集合包含了上百万条记录的情况,这个时候集合迭代就需要选择正确的姿势,否则性能会较差。
使用JMH检查下面每段代码片段的运行时间。
二、forEach vs. C Style vs. Stream API
迭代是一个非常基本的功能,所有的编程语言都有简单的迭代语法,允许程序员在集合上运行迭代。Stream API可以通过Collections用非常直接的方式进行迭代。
public List<Integer> streamSingleThread(BenchMarkState state) {
List<Integer> result = new ArrayList<>(state.testData.size());
state.testData.stream().forEach(item -> {
result.add(item);
});
return result;
}
public List<Integer> streamMultiThread(BenchMarkState state) {
List<Integer> result = new ArrayList<>(state.testData.size());
state.testData.stream().parallel().forEach(item -> {
result.add(item);
});
return result;
}
使用forEach循环也非常简单:
public List<Integer> forEach(BenchMarkState state) {
List<Integer> result = new ArrayList<>(state.testData.size());
for(Integer item : state.testData) {
result.add(item);
}
return result;
}
C style方式的迭代其代码要冗长一些,但仍然非常紧凑:
public List<Integer> forCStyle(BenchMarkState state) {
int size = state.testData.size();
List<Integer> result = new ArrayList<>(size);
for(int j = 0; j < size; j ++){
result.add(state.testData.get(j));
}
return result;
}
以上代码的性能评分如下:
Benchmark | Mode | Cnt | Score | Error | Units |
---|---|---|---|---|---|
TestLoopPerformance.forCStyle | avgt | 200 | 18.068 | ± 0.074 | ms/op |
TestLoopPerformance.forEach | avgt | 200 | 30.566 | ± 0.165 | ms/op |
TestLoopPerformance.streamMultiThread | avgt | 200 | 79.433 | ± 0.747 | ms/op |
TestLoopPerformance.streamSingleThread | avgt | 200 | 37.779 | ± 0.485 | ms/op |
对于C style方式的迭代,JVM只是简单地增加了一个整型变量,它直接从内存读值。这使它非常快。但forEach迭代则不同,根据Oracle官方文档,JVM必须把forEach转换为迭代器并为每个数据项调用hasNext()。这就是为什么forEach比C style

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
Java中如何创建一个确保唯一的名字,文件名
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客要讲的有,如何创建一个唯一的文件名,创建一个唯一的String字符串 为什么要创建唯一呢?再很多情况下,比如文件上传,文件名要不一致,否则就覆盖掉了,如何不一致,这就是本篇博客要讲的内容 注:直接采用随机数是愚蠢的做法,它在很大概率上会有相同的数字出现 方式一:时间戳 推荐指数: 原因:时间戳在高并发情况下有可能会出现相同 解决方案:再拼随机数,注意拼接的时候别让俩个做加法运算 时间戳变量+""+随机数变量 //时间戳第一种 System.out.println(new Date().getTime()); //时间戳第二种 System.out.println(System.currentTimeMillis()); 随机数: //生成六位随机数 System.out.println((int)((Math.random()*9+1)*100000)); 方式二:微秒数 推荐指数: 原因:它比时间戳还要细,控制的力度更强 也可以加随机数或者自己拼接自己的规则 //微秒数...
-
下一篇
(码友推荐)2018-07-14 .NET及相关开发资讯速递
(码友推荐)2018-07-14 .NET及相关开发资讯速递: 1.使用 Moq 测试.NET Core 应用 -- Mock 行为2.第四节:SignalR灵魂所在Hub模型及再探聊天室样例3.使用 Moq 测试.NET Core 应用 -- Mock 属性4.好代码是管出来的——.Net Core集成测试与数据驱动测试5.Docker and Azure Kubernetes Service for .NET Developers6.组件注册,通信,slot,复用,$mount()7.这58个收藏级 PPT 辅助网站,你都知道吗?8.怎样让用户对产品产生依赖与习惯?来看这篇基础科普!9.SignalR with ASP Net Core10..Net Core Cors中间件解析11.微软升级Windows记事本 原教旨主义程序员大欢喜12.使用 Moq 测试.NET Core 应用 -- Mock 方法13.[翻译]C# BAD PRACTICES: Learn how to make a good code by bad example---C#:如何将坏的代码重新编译为好的代...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合Redis,开启缓存,提高访问速度
- 设置Eclipse缩进为4个空格,增强代码规范
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2配置默认Tomcat设置,开启更多高级功能