HashMap循环遍历方式及其性能对比

2023-11-13

HashMap循环遍历方式及其性能对比

主要介绍HashMap的四种循环遍历方式,各种方式的性能测试对比,根据HashMap的源码实现分析性能结果,总结结论

 

1. Map的四种遍历方式
下面只是简单介绍各种遍历示例(以HashMap为例),各自优劣会在本文后面进行分析给出结论。

(1) for each map.entrySet()

Java
1
2
3
4
5
Map < String , String > map = new HashMap < String , String > ( ) ;
for ( Entry < String , String > entry : map . entrySet ( ) ) {
     entry . getKey ( ) ;
     entry . getValue ( ) ;
}

 

(2) 显示调用map.entrySet()的集合迭代器

Java
1
2
3
4
5
6
Iterator < Map . Entry < String , String >> iterator = map . entrySet ( ) . iterator ( ) ;
while ( iterator . hasNext ( ) ) {
     Map . Entry < String , String > entry = iterator . next ( ) ;
     entry . getKey ( ) ;
     entry . getValue ( ) ;
}

 

(3) for each map.keySet(),再调用get获取

Java
1
2
3
4
Map < String , String > map = new HashMap < String , String > ( ) ;
for ( String key : map . keySet ( ) ) {
     map . get ( key ) ;
}

 

(4) for each map.entrySet(),用临时变量保存map.entrySet()

Java
1
2
3
4
5
Set < Entry < String , String >> entrySet = map . entrySet ( ) ;
for ( Entry < String , String > entry : entrySet ) {
     entry . getKey ( ) ;
     entry . getValue ( ) ;
}

在测试前大家可以根据对HashMap的了解,想想上面四种遍历方式哪个性能更优。

 

2、HashMap四种遍历方式的性能测试及对比
以下是性能测试代码,会输出不同数量级大小的HashMap各种遍历方式所花费的时间。

HashMap循环遍历方式性能对比测试代码

PS:如果运行报异常in thread “main” java.lang.OutOfMemoryError: Java heap space,请将main函数里面map size的大小减小。

其中getHashMaps函数会返回不同size的HashMap。
loopMapCompare函数会分别用上面的遍历方式1-4去遍历每一个map数组(包含不同大小HashMap)中的HashMap。
print开头函数为输出辅助函数,可忽略。

 

测试环境为Windows7 32位系统 3.2G双核CPU 4G内存,Java 7,Eclipse -Xms512m -Xmx512m
最终测试结果如下:

Java
1
2
3
4
5
6
7
8
9
10
11
12
compare loop performance of HashMap
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
map size                | 10 , 000      | 100 , 000    | 1 , 000 , 000 | 2 , 000 , 000
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
for each entrySet        | 2 ms        | 6 ms        | 36 ms      | 91 ms     
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
for iterator entrySet    | 0 ms        | 4 ms        | 35 ms      | 89 ms     
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
for each keySet          | 1 ms        | 6 ms        | 48 ms      | 126 ms     
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
for entrySet = entrySet ( ) | 1 ms        | 4 ms        | 35 ms      | 92 ms     
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -

表横向为同一遍历方式不同大小HashMap遍历的时间消耗,纵向为同一HashMap不同遍历方式遍历的时间消耗。
PS:由于首次遍历HashMap会稍微多耗时一点,for each的结果稍微有点偏差,将测试代码中的几个Type顺序调换会发现,for each entrySet耗时和for iterator entrySet接近。

 

3、遍历方式性能测试结果分析
(1) foreach介绍

见:ArrayList和LinkedList的几种循环遍历方式及性能对比分析中介绍。

 

(2) HashMap遍历方式结果分析
从上面知道for each与显示调用Iterator等价,上表的结果中可以看出除了第三种方式(for each map.keySet()),再调用get获取方式外,其他三种方式性能相当。本例还是hash值散列较好的情况,若散列算法较差,第三种方式会更加耗时。
我们看看HashMap entrySet和keySet的源码

Java
1
2
3
4
5
6
7
8
9
10
11
private final class KeyIterator extends HashIterator <K> {
     public K next ( ) {
         return nextEntry ( ) . getKey ( ) ;
     }
}
 
private final class EntryIterator extends HashIterator < Map . Entry < K , V >> {
     public Map . Entry < K , V > next ( ) {
         return nextEntry ( ) ;
     }
}

分别是keySet()和entrySet()返回的set的迭代器,从中我们可以看到只是返回值不同而已,父类相同,所以性能相差不多。只是第三种方式多了一步根据key get得到value的操作而已。get的时间复杂度根据hash算法而异,源码如下:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public V get ( Object key ) {
     if ( key == null )
         return getForNullKey ( ) ;
     Entry < K , V > entry = getEntry ( key ) ;
 
     return null == entry ? null : entry . getValue ( ) ;
}
 
/**
* Returns the entry associated with the specified key in the
* HashMap.  Returns null if the HashMap contains no mapping
* for the key.
*/
final Entry < K , V > getEntry ( Object key ) {
     int hash = ( key == null ) ? 0 : hash ( key ) ;
     for ( Entry < K , V > e = table [ indexFor ( hash , table . length ) ] ;
         e != null ;
         e = e . next ) {
         Object k ;
         if ( e . hash == hash &&
             ( ( k = e . key ) == key || ( key != null && key . equals ( k ) ) ) )
             return e ;
     }
     return null ;
}

get的时间复杂度取决于for循环循环次数,即hash算法。

 

4、结论总结

从上面的分析来看:
a. HashMap的循环,如果既需要key也需要value,直接用

Java
1
2
3
4
5
Map < String , String > map = new HashMap < String , String > ( ) ;
for ( Entry < String , String > entry : map . entrySet ( ) ) {
     entry . getKey ( ) ;
     entry . getValue ( ) ;
}

即可,foreach简洁易懂。

b. 如果只是遍历key而无需value的话,可以直接用

Java
1
2
3
4
Map < String , String > map = new HashMap < String , String > ( ) ;
for ( String key : map . keySet ( ) ) {
     // key process
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HashMap循环遍历方式及其性能对比 的相关文章

  • 加密算法(DES,AES,RSA,MD5,SHA1,Base64)比较和项目应用, 各种加密算法比较

    加密算法 DES AES RSA MD5 SHA1 Base64 比较和项目应用 sochishun 博客园 https www cnblogs com sochishun p 7028056 html 加密算法 DES AES RSA M
  • 必须了解的Linux网络配置

    目录 一 查看及测试网络 1 1查看网络配置 1 2测试网络连接 二 设置网络地址参数 1 临时配置 使用命令调整网络参数 2 固定设置 通过配置文件修改网络参数 2 1 1 ifconfig命令 设置网络接口参数 2 1 2route命令
  • axios技术总结(包括跨域的处理)

    1 axios与vue axios 概念 axios是一个基于 promise 的 HTTP 库 可以用在浏览器和 node js 中 理解成库 vue axios用于将axios集成到Vuejs的小型包装器 理解成插件 安装 axios
  • Flink高手之路3-Flink的入门案例

    文章目录 Flink高手之路3 Flink的入门案例 一 Flink的API 二 Flink的编程模型 三 Flink的编程步骤 四 Flink的入门案例之一 批处理DataSet的处理 1 创建一个maven项目 2 改pom文件 引入F
  • Arduino ESP32 v2 使用记录:开发环境搭建

    文章目录 目的 开发环境搭建 程序下载测试 使用VS Code进行开发 批量烧录固件到模块中 总结 目的 在之前的文章 使用Arduino开发ESP32 01 开发环境搭建 中介绍了使用Arduino开发ESP32的开发环境搭建内容 只不过
  • hashmap和hashset的区别

    HashMap 和 HashSet 都是 Java 中的数据结构 它们都使用哈希表来实现 但是 它们之间有一些重要的区别 HashMap 是一种映射 它存储键值对 key value pairs 每个键都是唯一的 而值可以重复 HashSe
  • C++ 函数

    函数是一组一起执行一个任务的语句 每个 C 程序都至少有一个函数 即主函数 main 所有简单的程序都可以定义其他额外的函数 您可以把代码划分到不同的函数中 如何划分代码到不同的函数中是由您来决定的 但在逻辑上 划分通常是根据每个函数执行一
  • Linux查看日志

    很多初级测试人员 在进行执行测试用例这个步骤时 发现bug 不能更加的准确去定位bug 在这样的情况下就可以打开Linux服务器 敲命令查看操作进行中的实时日志 当系统报错时 可以截图日志在缺陷管理系统中 开发人员就知道什么地方错了 操作步
  • Unity物体碰撞出现穿插问题/穿过问题/物体穿过场景模型

    由于问题不好描述 所以标题就比较长了 之前在做游戏时 发生角色与其他模型始终不能正常碰撞 总是会穿插 即角色穿过其他模型 其中角色有刚体和碰撞器组件 其他模型 有 碰撞器 事后发现错误在于 其他模型的碰撞器组件被加到 组 上 而非组内每个物
  • Spring框架基础知识总结

    Spring框架 1 什么是Spring Spring是分层的Java SE EE应用 full stack轻量级开源框架 以IOC Inverse Of Control 反转控制 和AOP Aspect Oriented Programm
  • 1.3.3 手写数字识别之损失函数

    文章目录 概述 分类任务的损失函数 Softmax函数 交叉熵 交叉熵的代码实现 概述 上一节我们尝试通过更复杂的模型 经典的全连接神经网络和卷积神经网络 提升手写数字识别模型训练的准确性 本节我们继续将 横纵式 教学法从横向展开 如 图1
  • Ubuntu 20.04 下安装配置 VScode 的 C/C++ 开发环境

    前言 之前安装了Ubuntu 18 04 结果在安装Codeblocks VScode还是安装gcc c c 的时候出现了一堆错误 缺失依赖树等等问题 换源也无法成功 整了一个下午没有任何进展 网上找不到任何解决方法 于是只能重装了Ubun
  • 红队

    1 MS14 068 kerberos认证 no PAC 用户在向 Kerberos 密钥分发中心 KDC 申请TGT 由票据授权服务产生的身份凭证 时 可以伪造自己的 Kerberos 票据 漏洞效果 将任意域用户提升到域管权限 利用条件
  • promise的三种状态

    三种状态 es6 pending fufiled rejected 在promise种状态不可逆 时间不可倒流 promise时间有一个pending等待状态 如果实现fufiled状态 没实现rejected状态 解决了赘述问题 new
  • Redux使用教程【入门篇】

    Redux是一个用于JavaScript应用程序状态管理的可预测状态容器 以下是Redux的使用教程 安装Redux 在项目中使用npm或yarn安装Redux包 npm install redux 创建Redux Store 创建一个Re
  • vite、vue3警告:Component inside <Transition> renders non-element root node that cannot be animated.

    一 问题代码
  • 关于编程中的一些颜色代码

    颜色代码 1 浅粉色 255 182 193 2 粉红色 255 192 203 3 猩红色 220 20 60 4 脸红的淡紫色 255 240 245 5 苍白的紫罗兰红色 219 112 147 6 热情的粉红 255 105 180

随机推荐

  • 冰箱日订单数据分析(京东)python代码

    具体分析报告地址 PowerBi网页版 数据 2020年5月25日京东大家电 家用电器 冰箱订单数据 按10 抽样 约22MB 70k 条数据 包含信息 user log acct 用户账号 parent sale ord id 父订单号
  • Chrome等浏览器下出现net::ERR_BLOCKED_BY_CLIENT的解决办法

    当我们在做开发时 调试页面图片会出现部分图片无法正常显示 并且确认图片的地址正确 按F12 Debug查看报错原因 提示net ERR BLOCKED BY CLIENT错误 但当我们点击图片地址发现 图片地址并无错误 遇到这类情况 一般都
  • 关于一次element-ui的列表功能处理的过程记录(多选样式单选功能)

    大概是这样的 这边需要做两个表格 一个在左边 一个在右边 左边的已经做好了 是一个多选列表 右边的也做好了 是一个element ui自带的单选列表 就像这样 可是左边的多选列表样式和这个不一样 看着就会比较怪 所以要求我去修样式 我有点蒙
  • uni-app使用npm安装第三方包

    初始化npm工程 若项目之前未使用npm管理依赖 项目根目录下无package json文件 先在项目根目录执行命令初始化npm工程 npm init y cli项目默认已经有package json了 HBuilderX创建的项目默认没有
  • socket.io 中namespace 和 room的概念。

    基本概念看socketio官方文档 http socket io docs rooms and namespaces namespace 和room的概念其实用来同一个服务端socket多路复用的 namespace room和socket
  • PHP利用SOAP进行webservice开发(客户端)

    参考 http blog sina com cn s blog 777f9dbb01010fd1 html 配置 windows php ini配置 extension php soap dll extension php curl dll
  • linux主要的文件和目录的作用(详细版)

    在 Linux 下 我们看到的是文件夹 目录 在早期的 UNIX 系统中 各个厂家各自定义了自己的 UNIX 系统文件目录 比较混乱 Linux 面世不久后 对文件目录进行了标准化 于1994年对根文件目录做了统一的规范 推出 FHS Fi
  • DirectShowPlayerService::doSetUrlSource: Unresolved error code

    Qt 编译后不能播放音乐或者视频 经过搜索得知 Qt 中的多媒体播放 底层是使用DirectShowPlayerService 需要一个DirectShow解码器 例如LAV Filters LAV Filters的下载地址如下 http
  • FPGA的基本结构

    FPGA主要由以下几部分组成 1 基本可编程逻辑单元 CLB 2 可编程输入输出单元 IOB 3 嵌入式块RAM 4 内嵌的底层功能单元和嵌入式专用硬核 5 完整的时钟管理模块 6 丰富的布线资源 一 总体结构 二 基本组成部分 1 可配置
  • NMS(非极大值抑制)算法详解与示例

    一 NMS是什么 NMS non maximum suppression 即非极大值抑制 广泛应用于传统的特征提取和深度学习的目标检测算法中 NMS原理是通过筛选出局部极大值得到最优解 在2维边缘提取中体现在提取边缘轮廓后将一些梯度方向变化
  • vue设置延时

    参考资料 https blog csdn net zc ad article details 86235227 一定要创建一个timer 然后调用延时之前先清除timer的延时 clearTimeout this timer 清除延迟执行
  • scala数据结构

    元组 val tuple Bigdata 2020 748 333 容器 collection Scala Collection Seq 索引0 1 2 LinearSeq gt 列表 相同类型 不可变 队列 列表 var strList
  • SpringIOC和AOP介绍

    Spring介绍 1 spring是轻量级的开源的JavaEE框架 2 Spring可以解决企业应用开发的复杂性 3 Spring有两个核心部分 IOC AOP 1 IOC 控制反转 把创建好的对象给Spring进行管理 2 AOP 面向切
  • 模式识别、计算机视觉、机器学习领域的顶级期刊和会议(整理)

    部分AI刊物影响因子05 SCIIF 2005 2004 JMLR 4 027 5 952 机器学习 PAMI 3 810 4 352 模式识别 IJCV 3 657 2 914 计算机视觉 TOIS 4 529 4 097 AIJ 2 6
  • Neo4j下载安装以及Neo4j浏览器详细说明

    1 下载 需要提前安装 JDK 自行百度 前往官网 https neo4j com download center community 如上图 下载共有三个模式 企业版本 社区版本和桌面版本 企业版本收费的 社区版本免费 只是个人运行建议直
  • 请告诉我一些常见的泰勒公式展开

    常见的泰勒公式展开有 1 二项式展开 x y n nCkx n k y k 2 三角形展开 a b c 2 a 2 b 2 c 2 2ab 2ac 2bc 3 多项式展开 x y z 3 x 3 y 3 z 3 3x 2y 3x 2z 3x
  • 勤于奋:的日常,写程序,做任务,赚美刀,分享我的成长

    大家好 欢迎来到勤于奋 今天跟大家聊聊我的日常吧 大家好 欢迎来到勤于奋国外LEAD联盟营销 勤于奋时刻提醒自己 只有勤快和奋斗合一体 天天坚持去做一件事情 才能有可能成功 所以我很喜欢这个名字 每天我都会关注程序语言的发展 开发技术的更新
  • springboot 2.7集成swagger 3

    目录 前言 错误原因 报错内容 报错原因 解决方案 依赖配置 webmvc配置 swagger配置 结果 前言 springboot集成swagger2技术比较成熟 基本不挑版本 网上技术文章一找一大堆 不在此赘述 但是sprngboot
  • 线路编码(NRZ,NRZI,8B/10B,Manchester等)

    0 前言 编码根据作用和场景不同分为信源编码 信道编码和线路编码 信源编码 降低信源符号之间的相关性和冗余度 通过编码提高每个符号的信息量 具体说 就是针对信源输出符号序列的统计特性来寻找某种方法 把信源输出符号序列变换为最短的码字序列 比
  • HashMap循环遍历方式及其性能对比

    HashMap循环遍历方式及其性能对比 主要介绍HashMap的四种循环遍历方式 各种方式的性能测试对比 根据HashMap的源码实现分析性能结果 总结结论 1 Map的四种遍历方式 下面只是简单介绍各种遍历示例 以HashMap为例 各自