Java性能优化-HashMap遍历的7种方式及性能测试对比

场景

Java中使用JMH(Java Microbenchmark Harness 微基准测试框架)进行性能测试和优化:

Java中使用JMH(Java Microbenchmark Harness 微基准测试框架)进行性能测试和优化_java热点函数-CSDN博客

参考以上性能测试工具的使用。下面针对Java中对HashMap的7种遍历方式做性能测试。

注:

博客:
霸道流氓气质-CSDN博客

实现

Java中HashMap遍历的方式

HashMap遍历,从大的方向来说,可分为以下4类:

1、迭代器(Iterator)方式遍历

2、For Each方式遍历

3、Lambda表达式遍历(JDK 1.8+)

4、Streams API遍历(JDK1.8+)

但每种类型下又有不同的实现方式,因此具体的遍历⽅式又可以分为以下7种:

1. 使⽤迭代器(Iterator)EntrySet 的⽅式进⾏遍历;

    public static void EntrySetForEach(){//创建并赋值HashMapMap<Integer,String> map = new HashMap<>();map.put(1,"公众号");map.put(2,"霸道的程序猿");map.put(3,"测试1");map.put(4,"测试2");map.put(5,"测试3");//遍历Iterator<Map.Entry<Integer,String>> iterator = map.entrySet().iterator();while (iterator.hasNext()){Map.Entry<Integer,String> entry = iterator.next();System.out.println(entry.getKey());System.out.println(entry.getValue());}}

2. 使⽤迭代器(Iterator)KeySet 的⽅式进⾏遍历;

    public static void KeySetForEach(){Map<Integer,String> map = new HashMap<>();map.put(1,"公众号");map.put(2,"霸道的程序猿");map.put(3,"测试1");map.put(4,"测试2");map.put(5,"测试3");Iterator<Integer> iterator = map.keySet().iterator();while(iterator.hasNext()){Integer key = iterator.next();System.out.println(key);System.out.println(map.get(key));}}

3. 使⽤ For Each EntrySet 的⽅式进⾏遍历;

    public static void ForEachEntrySet(){Map<Integer,String> map = new HashMap<>();map.put(1,"公众号");map.put(2,"霸道的程序猿");map.put(3,"测试1");map.put(4,"测试2");map.put(5,"测试3");for (Map.Entry<Integer,String> entry:map.entrySet()) {System.out.println(entry.getKey());System.out.println(entry.getValue());}}

4. 使⽤ For Each KeySet 的⽅式进⾏遍历;

    public static void ForEachKeySet(){Map<Integer,String> map = new HashMap<>();map.put(1,"公众号");map.put(2,"霸道的程序猿");map.put(3,"测试1");map.put(4,"测试2");map.put(5,"测试3");for(Integer key:map.keySet()){System.out.println(key);System.out.println(map.get(key));}}

5. 使⽤ Lambda 表达式的⽅式进⾏遍历;

    public static void LambdaForEach(){Map<Integer,String> map = new HashMap<>();map.put(1,"公众号");map.put(2,"霸道的程序猿");map.put(3,"测试1");map.put(4,"测试2");map.put(5,"测试3");map.forEach((key,value)->{System.out.println(key);System.out.println(value);});}

6. 使⽤ Streams API 单线程的⽅式进⾏遍历;

    public static void StreamSingle(){Map<Integer,String> map = new HashMap<>();map.put(1,"公众号");map.put(2,"霸道的程序猿");map.put(3,"测试1");map.put(4,"测试2");map.put(5,"测试3");map.entrySet().stream().forEach((entry)->{System.out.println(entry.getKey());System.out.println(entry.getValue());});}

7. 使⽤ Streams API 多线程的⽅式进⾏遍历。

    public static void StreamMul(){Map<Integer,String> map = new HashMap<>();map.put(1,"公众号");map.put(2,"霸道的程序猿");map.put(3,"测试1");map.put(4,"测试2");map.put(5,"测试3");map.entrySet().parallelStream().forEach((entry)->{System.out.println(entry.getKey());System.out.println(entry.getValue());});}

Java中7种遍历HashMap方式性能测试

编写如下测试类

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;//测试完成时间
@BenchmarkMode(Mode.AverageTime)
//设置统计结果的时间单位
@OutputTimeUnit(TimeUnit.NANOSECONDS)
//预热所需要配置的一些基本测试参数,可用于类或者方法上。一般前几次进行程序测试的时候都会比较慢,所以要让程序进行几轮预热,保证测试的准确性。参数如下所示:
//
//iterations:预热的次数
//time:每次预热的时间
//timeUnit:时间的单位,默认秒
//batchSize:批处理大小,每次操作调用几次方法
//因为 JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译为机器码,从而提高执行速度,
//所以为了让 benchmark 的结果更加接近真实情况就需要进行预热。
@Warmup(iterations = 2,time = 1,timeUnit = TimeUnit.SECONDS)
//测试次数和时间,参数同上
@Measurement(iterations = 5,time = 1,timeUnit = TimeUnit.SECONDS)
//fork一个线程,进行 fork 的次数,可用于类或者方法上。如果 fork 数是 2 的话,则 JMH 会 fork 出两个进程来进行测试。
@Fork(1)
//通过 State 可以指定一个对象的作用范围,JMH 根据 scope 来进行实例化和共享操作。@State 可以被继承使用,
//如果父类定义了该注解,子类则无需定义。由于 JMH 允许多线程同时执行测试,不同的选项含义如下:
//Scope.Benchmark:所有测试线程共享一个实例,测试有状态实例在多线程共享下的性能
//Scope.Group:同一个线程在同一个 group 里共享实例
//Scope.Thread:默认的 State,每个测试线程分配一个实例
@State(Scope.Thread)
public class HashMapCycleTest {static Map<Integer,String> map = new HashMap(){{for(int i = 0;i<100;i++){put(i,"value"+i);}}};public static void main(String[] args) throws RunnerException {//启动基准测试Options options = new OptionsBuilder().include(HashMapCycleTest.class.getSimpleName())//要导入的测试类.build();new Runner(options).run();//执行测试}@Benchmarkpublic void EntrySetForEach(){//遍历Iterator<Map.Entry<Integer,String>> iterator = map.entrySet().iterator();while (iterator.hasNext()){Map.Entry<Integer,String> entry = iterator.next();Integer key = entry.getKey();String value = entry.getValue();}}@Benchmarkpublic  void KeySetForEach(){Iterator<Integer> iterator = map.keySet().iterator();while(iterator.hasNext()){Integer key = iterator.next();String value = map.get(key);}}@Benchmarkpublic  void ForEachEntrySet(){for (Map.Entry<Integer,String> entry:map.entrySet()) {Integer key = entry.getKey();String value = entry.getValue();}}@Benchmarkpublic  void ForEachKeySet(){for(Integer key:map.keySet()){Integer k = key;String value = map.get(key);}}@Benchmarkpublic  void LambdaForEach(){map.forEach((key,value)->{Integer k = key;String v = value;});}@Benchmarkpublic void StreamSingle(){map.entrySet().stream().forEach((entry)->{Integer k = entry.getKey();String v = entry.getValue();});}}

运行测试类

所有被添加了 @Benchmark 注解的⽅法都会被测试,因为 parallelStream 为多线程版本性能⼀定是最好的,所以就不参与测试了

测试结果

//Benchmark                         Mode  Cnt    Score     Error  Units
//HashMapCycleTest.EntrySetForEach  avgt    5  543.154 ±  36.365  ns/op
//HashMapCycleTest.ForEachEntrySet  avgt    5  533.511 ±  42.878  ns/op
//HashMapCycleTest.ForEachKeySet    avgt    5  805.146 ± 118.210  ns/op
//HashMapCycleTest.KeySetForEach    avgt    5  785.286 ±  68.913  ns/op
//HashMapCycleTest.LambdaForEach    avgt    5  429.048 ±  47.000  ns/op
//HashMapCycleTest.StreamSingle     avgt    5  501.687 ±  25.401  ns/op

结论:

从以上结果可以看出, lambda表达式和两个entrySet的性能相近,并且执⾏速度最快,接下来是 stream ,

然后是两个 keySet 。如果从性能⽅⾯考虑,我们应该尽量使⽤ lambda 或者是 entrySet 来遍历 Map 集合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/45304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《梦醒蝶飞:释放Excel函数与公式的力量》11.3 ISTEXT函数

第11章&#xff1a;信息函数 第三节 11.3 ISTEXT函数 11.3.1 简介 ISTEXT函数是Excel中的一个信息函数&#xff0c;用于检查指定单元格中的内容是否为文本。如果单元格内容是文本&#xff0c;则返回TRUE&#xff1b;否则返回FALSE。ISTEXT函数在数据验证、条件格式化和逻辑判…

社区团购小程序源码系统 带完整的安装代码以及搭建部署教程

系统概述 在这个数字化时代&#xff0c;线上活动成为了连接用户与组织者的桥梁。为了满足不同场景的需要&#xff0c;开发一个灵活、可定制的在线活动报名表单小程序显得尤为重要。本文将深入介绍一个自定义在线活动报名表单小程序的源码系统&#xff0c;并提供详细的搭建部署…

Android高级——Logger日志系统

Logger日志系统 Logger日志系统是基于内核中的Logger日志驱动程序实现将日志记录保存在内核空间中使用一个环形缓冲区来保存日志&#xff0c;满了之后&#xff0c;新的日志就会覆盖旧的日志 日志类型 main&#xff0c;记录应用程序级别system&#xff0c;记录系统级别radio&…

在Ubuntu下安装samba实现和Windows系统文件共享

一、安装 apt install -y samba samba-clientSamba is not being run as an AD Domain Controller: Masking samba-ad-dc.service Please ignore the following error about deb-systemd-helper not finding those services. (samba-ad-dc.service masked) Created symlink /et…

百度网盘资料使用

1. 将链接复制到浏览器打开&#xff0c;点击提取文件 2. 提取文件&#xff0c;进入如下界面 3. 因为文件太大&#xff0c;而且未开会员&#xff0c;所以无法全部转存到网盘&#xff0c;只能分批次转存 点击目录&#xff0c;进入文件夹 1&#xff09;选择一个喜欢的文件&#…

9.Python学习:Socket

1.网络通信要素&#xff08;IP端口传输协议&#xff09; 2.Socket编程 2.1TCP、UDP协议了解 2.2 Socket流程 服务端有两个socket对象&#xff0c;客户端有一个 3.Socket实战 服务端代码&#xff1a; import socket #创建Socket对象 sksocket.socket() #绑定ip与端口号-使…

在分布式环境中,怎样保证 PostgreSQL 数据的一致性和完整性?

文章目录 在分布式环境中保证 PostgreSQL 数据的一致性和完整性一、数据一致性和完整性的重要性二、分布式环境对数据一致性和完整性的挑战&#xff08;一&#xff09;网络延迟和故障&#xff08;二&#xff09;并发操作&#xff08;三&#xff09;数据分区和复制 三、保证 Pos…

Apache Spark分布式计算框架架构介绍

目录 一、概述 二、Apache Spark架构组件栈 2.1 概述 2.2 架构图 2.3 架构分层组件说明 2.3.1 支持数据源 2.3.2 调度运行模式 2.3.3 Spark Core核心 2.3.3.1 基础设施 2.3.3.2 存储系统 2.3.3.3 调度系统 2.3.3.4 计算引擎 2.3.4 生态组件 2.3.4.1 Spark SQL 2.…

网络基础:Vlan原理与配置

VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网&#xff09;是一种将一个物理网络划分为多个逻辑子网的技术。它通过在网络交换机上配置&#xff0c;使得不同VLAN中的设备即使连接在同一个物理交换机上&#xff0c;也不能直接进行通信&#xff0c;从而实现…

某企业数据治理总体解决方案(45页PPT)

引言&#xff1a;集团企业数据治理总体解决方案旨在构建一个高效、安全、合规且灵活的数据管理体系&#xff0c;以支持企业决策优化、业务创新、风险管理和运营效率提升。该方案通过整合数据资源、规范数据流程、强化数据质量和促进数据共享&#xff0c;实现数据资产的最大化价…

Lingo学习(三)——工厂合并、运算符、内置函数

一、工厂合并 &#xff08;一&#xff09; 工厂合并——生产二维矩阵 【引入】 sets: factory /1..6/ : a; plant /1..8/ : d; Cooperation(factory,p lant) : c, x; endsets 以上程序可…

【YOLOv8】 用YOLOv8实现数字式工业仪表智能读数(三)

上一篇圆形表盘指针式仪表的项目受到很多人的关注&#xff0c;咱们一鼓作气&#xff0c;把数字式工业仪表的智能读数也研究一下。本篇主要讲如何用YOLOV8实现数字式工业仪表的自动读数&#xff0c;并将读数结果进行输出&#xff0c;若需要完整数据集和源代码可以私信。 目录 &a…

网络安全应急响应信息收集利器-Eagle_Eye

项目介绍: 网络安全应急响应信息收集利器 - Eagle_Eye&#xff1a;您的终端信息自动收集专家 在网络安全的紧急时刻&#xff0c;每一秒都至关重要。Eagle_Eye&#xff0c;这款专为应急响应设计的工具&#xff0c;如同一位随时待命的侦察兵&#xff0c;能够在危机时刻迅速收集…

嵌入式工程师从0开始,到底该学什么,怎么学?

作为嵌入式工程师&#xff0c;从零开始学习需要掌握以下几个关键方面。我收集归类了一份嵌入式学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的学习方向编程教学、问题视频讲解、毕设800套和语言类教学&#xff0c;敲个22就可以免费获得。 基…

yarn底层原理详解:(第33天)

系列文章目录 一、yarn总体架构 二、yarn核心组件及功能 三、yarn资源分配与调度 四、yarn提交和执行流程 五、yarn调度算法 六、yarn安全性与容错性 文章目录 系列文章目录前言一、总体架构二、核心组件及功能1. ResourceManager&#xff08;RM&#xff09;2. NodeManager&am…

day29--452. 用最少数量的箭引爆气球+435. 无重叠区间+763.划分字母区间

一、452. 用最少数量的箭引爆气球 题目链接&#xff1a;https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/ 文章讲解&#xff1a;https://programmercarl.com/0452.%E7%94%A8%E6%9C%80%E5%B0%91%E6%95%B0%E9%87%8F%E7%9A%84%E7%AE%AD%E5%BC%95%E7%88…

整数的英语表示

题目链接 整数的英语表示 题目描述 注意点 0 < num < 2^31 - 1 解答思路 每三个数字形成一组&#xff08;高位不足的部分可以用0填充&#xff09;&#xff0c;使用StringBuilder拼接每组的数字和单位关键是三个数字的英语表示&#xff0c;包含个位、十位、百位&…

C++ | Leetcode C++题解之第229题多数元素II

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> majorityElement(vector<int>& nums) {int n nums.size();vector<int> ans;unordered_map<int, int> cnt;for (auto & v : nums) {cnt[v];}for (auto & v : cnt…

搭建ELK+Filebead+zookeeper+kafka实验

目录 1.部署 Filebeat 2. Logstash配置 3.浏览器kibana访问验证 主机名ip地址主要软件es01192.168.9.114ElasticSearches02192.168.9.115ElasticSearches03192.168.9.116ElasticSearch、Kibananginx01192.168.9.113nginx、LogstashNA192.168.9.111nginx、FilebeatNA192.168…

YOLOv8改进 | 注意力机制| 对小目标友好的BiFormer【CVPR2023】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效…