map for循环_阿里面试问我hashMap的循环姿势有哪几种?
hashMap 应该是java程序员工作中用得比较多的一个键值对处理的数据的类型了。这种数据类型一般都会有增删查的方法,今天我们就来看看它的循环方法以前写过一篇关于ArrayList的循环效率问题《ArrayList哪种遍历效率最好,你真的弄明白了吗?》,感兴趣的同学可以去看看。hashMap 有常见的六七种遍历的方式。这么多的选择,大家平时都是使用哪一种来遍历数据列?欢迎大家在下方留言哦。说实话这么多种方式,想记也不记不住,也不想浪费时间来记这玩意,所以本人在JDK1.8以前基本上都是用Map.Entry的方式来遍历,1.8及以后就习惯性用forEach了,不过这个不能有continue或者break操作这个有时候还是挺不方便的,其他几种基本上没怎么用过,也没太研究这几种方式,哪种性能是比较好的。反正就是挑自己熟悉的方式。好了话不多说,我们还是直入今天的主题。先来看看每种遍历的方式:
在for循环中使用entries实现Map的遍历
public static void forEachEntries() { for (Map.Entry entry : map.entrySet()) { String mapKey = entry.getKey(); String mapValue = entry.getValue(); } }
在for循环中遍历key
public static void forEachKey() { for (String key : map.keySet()) { String mapKey = key; String mapValue = map.get(mapKey); } }
在for循环中遍历value
public static void forEachValues() { for (String key : map.values()) { String val = key; } }
Iterator遍历
public static void forEachIterator() { Iterator> entries = map.entrySet().iterator(); while (entries.hasNext()) { Entry entry = entries.next(); String key = entry.getKey(); String value = entry.getValue(); } }
forEach jdk1.8遍历
public static void forEach() { map.forEach((key, val) -> { String key1 = key; String value = val; }); }
Stream jdk1.8遍历
map.entrySet().stream().forEach((entry) -> { String key = entry.getKey(); String value = entry.getValue(); });
Streamparallel jdk1.8遍历
public static void forEachStreamparallel() { map.entrySet().parallelStream().forEach((entry) -> { String key = entry.getKey(); String value = entry.getValue(); }); }
以上就是常见的对于map的一些遍历的方式,下面我们来写个测试用例来看下这些遍历方式,哪些是效率最好的。下面测试用例是基于JMH来测试的 首先引入pom
org.openjdk.jmh jmh-core 1.23org.openjdk.jmh jmh-generator-annprocess 1.23provided
关于jmh测试如可能会影响结果的一些因素这里就不详细介绍了,可以参考文末的第一个链接写得非常详细。以及测试用例为什么要这么写(都是为了消除JIT对测试代码的影响)这是参照官网的链接: 编写测试代码如下:
package com.workit.autoconfigure.autoconfigure.controller;import org.openjdk.jmh.annotations.*;import org.openjdk.jmh.infra.Blackhole;import org.openjdk.jmh.results.format.ResultFormatType;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.Map.Entry;import java.util.UUID;import java.util.concurrent.TimeUnit;/** * @author:公众号: java金融 * @Date: * @Description:微信搜一搜【java金融】回复666 */@State(Scope.Thread)@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)@Fork(1)@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.NANOSECONDS)public class InstructionsBenchmark { public static void main(String[] args) throws RunnerException { Options opt = new OptionsBuilder().include(InstructionsBenchmark.class.getSimpleName()).result("result.json").resultFormat(ResultFormatType.JSON).build(); new Runner(opt).run(); } static final int BASE = 42; static int add(int key,int val) { return BASE + key +val; } @Param({"1", "10", "100", "1000","10000","100000"}) int size; private static Map map; // 初始化方法,在全部Benchmark运行之前进行 @Setup(Level.Trial) public void init() { map = new HashMap<>(size); for (int i = 0; i < size; i++) { map.put(i, i); } } /** * 在for循环中使用entries实现Map的遍历: */ @Benchmark public static void forEachEntries(Blackhole blackhole) { for (Map.Entry entry : map.entrySet()) { Integer mapKey = entry.getKey(); Integer mapValue = entry.getValue(); blackhole.consume(add(mapKey,mapValue)); } } /** * 在for循环中遍历key */ @Benchmark public static StringBuffer forEachKey(Blackhole blackhole) { StringBuffer stringBuffer = new StringBuffer(); for (Integer key : map.keySet()) { // Integer mapValue = map.get(key); blackhole.consume(add(key,key)); } return stringBuffer; } /** * 在for循环中遍历value */ @Benchmark public static void forEachValues(Blackhole blackhole) { for (Integer key : map.values()) { blackhole.consume(add(key,key)); } } /** * Iterator遍历; */ @Benchmark public static void forEachIterator(Blackhole blackhole) { Iterator> entries = map.entrySet().iterator(); while (entries.hasNext()) { Entry entry = entries.next(); Integer key = entry.getKey(); Integer value = entry.getValue(); blackhole.consume(add(key,value)); } } /** * forEach jdk1.8遍历 */ @Benchmark public static void forEachLamada(Blackhole blackhole) { map.forEach((key, value) -> { blackhole.consume(add(key,value)); }); } /** * forEach jdk1.8遍历 */ @Benchmark public static void forEachStream(Blackhole blackhole) { map.entrySet().stream().forEach((entry) -> { Integer key = entry.getKey(); Integer value = entry.getValue(); blackhole.consume(add(key,value)); }); } @Benchmark public static void forEachStreamparallel(Blackhole blackhole) { map.entrySet().parallelStream().forEach((entry) -> { Integer key = entry.getKey(); Integer value = entry.getValue(); blackhole.consume(add(key,value)); }); }}
运行结果如下: 「注:运行环境idea 2019.3,jdk1.8,windows7 64位。」
Benchmark (size) Mode Cnt Score Error UnitsInstructionsBenchmark.forEachEntries 1 avgt 5 10.021 ± 0.224 ns/opInstructionsBenchmark.forEachEntries 10 avgt 5 71.709 ± 2.537 ns/opInstructionsBenchmark.forEachEntries 100 avgt 5 738.873 ± 12.132 ns/opInstructionsBenchmark.forEachEntries 1000 avgt 5 7804.431 ± 136.635 ns/opInstructionsBenchmark.forEachEntries 10000 avgt 5 88540.345 ± 14915.682 ns/opInstructionsBenchmark.forEachEntries 100000 avgt 5 1083347.001 ± 136865.960 ns/opInstructionsBenchmark.forEachIterator 1 avgt 5 10.675 ± 2.532 ns/opInstructionsBenchmark.forEachIterator 10 avgt 5 73.934 ± 4.517 ns/opInstructionsBenchmark.forEachIterator 100 avgt 5 775.847 ± 198.806 ns/opInstructionsBenchmark.forEachIterator 1000 avgt 5 8905.041 ± 1294.618 ns/opInstructionsBenchmark.forEachIterator 10000 avgt 5 98686.478 ± 10944.570 ns/opInstructionsBenchmark.forEachIterator 100000 avgt 5 1045309.216 ± 36957.608 ns/opInstructionsBenchmark.forEachKey 1 avgt 5 18.478 ± 1.344 ns/opInstructionsBenchmark.forEachKey 10 avgt 5 76.398 ± 12.179 ns/opInstructionsBenchmark.forEachKey 100 avgt 5 768.507 ± 23.892 ns/opInstructionsBenchmark.forEachKey 1000 avgt 5 11117.896 ± 1665.021 ns/opInstructionsBenchmark.forEachKey 10000 avgt 5 84871.880 ± 12056.592 ns/opInstructionsBenchmark.forEachKey 100000 avgt 5 1114948.566 ± 65582.709 ns/opInstructionsBenchmark.forEachLamada 1 avgt 5 9.444 ± 0.607 ns/opInstructionsBenchmark.forEachLamada 10 avgt 5 76.125 ± 5.640 ns/opInstructionsBenchmark.forEachLamada 100 avgt 5 861.601 ± 98.045 ns/opInstructionsBenchmark.forEachLamada 1000 avgt 5 7769.714 ± 1663.914 ns/opInstructionsBenchmark.forEachLamada 10000 avgt 5 73250.238 ± 6032.161 ns/opInstructionsBenchmark.forEachLamada 100000 avgt 5 836781.987 ± 72125.745 ns/opInstructionsBenchmark.forEachStream 1 avgt 5 29.113 ± 3.275 ns/opInstructionsBenchmark.forEachStream 10 avgt 5 117.951 ± 13.755 ns/opInstructionsBenchmark.forEachStream 100 avgt 5 1064.767 ± 66.869 ns/opInstructionsBenchmark.forEachStream 1000 avgt 5 9969.549 ± 342.483 ns/opInstructionsBenchmark.forEachStream 10000 avgt 5 93154.061 ± 7638.122 ns/opInstructionsBenchmark.forEachStream 100000 avgt 5 1113961.590 ± 218662.668 ns/opInstructionsBenchmark.forEachStreamparallel 1 avgt 5 65.466 ± 5.519 ns/opInstructionsBenchmark.forEachStreamparallel 10 avgt 5 2298.999 ± 721.455 ns/opInstructionsBenchmark.forEachStreamparallel 100 avgt 5 8270.759 ± 1801.082 ns/opInstructionsBenchmark.forEachStreamparallel 1000 avgt 5 16049.564 ± 1972.856 ns/opInstructionsBenchmark.forEachStreamparallel 10000 avgt 5 69230.849 ± 12169.260 ns/opInstructionsBenchmark.forEachStreamparallel 100000 avgt 5 638129.559 ± 14885.962 ns/opInstructionsBenchmark.forEachValues 1 avgt 5 9.743 ± 2.770 ns/opInstructionsBenchmark.forEachValues 10 avgt 5 70.761 ± 16.574 ns/opInstructionsBenchmark.forEachValues 100 avgt 5 745.069 ± 329.548 ns/opInstructionsBenchmark.forEachValues 1000 avgt 5 7772.584 ± 1702.295 ns/opInstructionsBenchmark.forEachValues 10000 avgt 5 74063.468 ± 23752.678 ns/opInstructionsBenchmark.forEachValues 100000 avgt 5 994057.370 ± 279310.867 ns/op
通过上述的图我们可以发现,数据量较小的时候forEachEntries和forEachIterator、以及lamada循环效率都差不多forEachStreamarallel的效率反而较低,只有当数据量达到10000以上parallelStream的优势就体现出来了。所以平时选择使用哪种循环方式的时候没必要太纠结哪一种方式,其实每种方式之间的效率还是微乎其微的。选择适合自己的就好。为什么parallelStream在数据量较小的时候效率反而不行?这个大家可以在下方留言哦。
总结
上面小实验只是在我机器上跑出来的结果,可能放到不同的机器运行结果有不一样哦,大家感兴趣的同学可以把代码贴到自己的机器上跑一跑,也许我这这个结论就不适用了。
结束
- 由于自己才疏学浅,难免会有纰漏,假如你发现了错误的地方,还望留言给我指出来,我会对其加以修正。
- 如果你觉得文章还不错,你的转发、分享、赞赏、点赞、留言就是对我最大的鼓励。
- 感谢您的阅读,十分欢迎并感谢您的关注。 巨人的肩膀摘苹果: https://www.cnkirito.moe/java-jmh/ https://jmh.morethan.io/
map for循环_阿里面试问我hashMap的循环姿势有哪几种?相关推荐
- 的 while循环_十八、Python图解while循环
人生苦短,要学Python Python中循环有while循环和for循环,接下来将介绍Python中的while循环和for循环. while循环 语法格式 # while语句用于循环执行程序,也就 ...
- 跳出多重循环_代码里的俄罗斯套娃 | 07 多重循环
点击上方 蓝字 关注我们 前情提要:刚上二年级的小红正在学习九九乘法表,老师说明天上课时要抽查,但她总是记不熟,你能写个程序帮帮她吗? 是不是想到了我们上一期学的For循环遍历,刚好可以用上.但好像又 ...
- shell脚本for循环_了解Shell脚本中的for循环
shell脚本for循环 Continuing on from our previous tutorials, let's understand the for loop in shell scrip ...
- django中的for循环_深入了解 JavaScript 中的 for 循环
在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是: 简单for循环 for-in forEach 在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循 ...
- vba循环通过键盘某个按键按下退出循环_[VBA]For Next与Do Loop循环
" 在黑夜中前行,行也寂寞,停也寂寞 " (更文的时候,正好最近发生许多事,算是做个自我安慰吧) 作为VBA的基本语句,For Next和Do Loop都是很早进入初学者学习的循环 ...
- python并发循环_在Python中模拟一个并发循环?
在Python中模拟一个并发循环? 我需要模拟Python程序中的并发循环.不幸的是,以下简单的代码不起作用:list_of_ints = [ 1, 2, 3 ]iterator = list_of_ ...
- python种颜色循环_使用matplotlib颜色图进行颜色循环 - python
如果我通过以下方式创建颜色: 将numpy导入为np 从matplotlib导入pyplot作为plt n = 6 color = plt.cm.coolwarm(np.linspace(0.1,0. ...
- java 暂停循环_在用于暂停线程时,循环Thread.Sleep()会不会对性能造成影响?...
有(或者已经有)很多关于使用 Thread.Sleep() 方法的好坏的讨论 . 据我所知,它主要用于调试目的 . 现在我想知道:用于我的特定目的是不是很糟糕,也就是说,不断循环它以便能够暂停/恢复线 ...
- python读取二进制数据中的while循环_在Python中读取二进制文件并循环遍历每个字节...
f = open("myfile", "rb") try: byte = f.read(1) while byte != "": # Do ...
最新文章
- VS Code竟然能约会,找对象不看脸,看编程水平
- Java中的异常和递归
- 安卓给string对象赋值_String 面试题!看完让你恍然大悟!
- Cropper – 简单的 jQuery 图片裁剪插件
- 引入 javascript_在您JavaScript项目中引入类型安全性? 再想一想
- IBM 发布企业级社交协作平台 Domino V10,开启快速应用程序开发的新时代
- C++中typedef void(*F)(类型)解读
- 获取键盘上某键的状态
- ae怎么输入竖排文字? ae文字竖排的方法
- 能量换算,方便减肥控制饮食
- Blender 建模
- 117. 请简述文本文件和二进制文件的区别
- dcdc模块降额设计_爱默生网络能源PCB设计规范
- Java接口的基本概念详解
- 如何快速推广引流?利用微博截流疯狂获取流量
- 雨听 | 英语学习笔记(十二)~作文范文:成绩与能力
- 欧几里得算法和扩展欧几里得算法——杨子曰数学
- windows系统DOS窗口
- VSCODE 使用One Dark Pro并优化
- STM32与SYN6288语音合成模块的使用
热门文章
- Linux学习总结(67)——shell脚本中$0 $1 $# $@ $* $? $ 等总结
- Json学习总结(8)——经过多方调研,最终还是决定禁用FastJson
- Mysql学习总结(48)——MySql的日志与备份还原
- Java基础学习总结(53)——HTTPS 理论详解与实践
- Java基础学习总结(32)——Java项目命名规范
- Maven学习总结(4)——Maven核心概念
- html表格中加横线,表格下划线怎么打出来
- char(128) mysql_char能表示(-128~127)
- php自学目录,PHP学习笔记(二) 了解PHP的基本语法以及目录结构
- CentOS6.5下的Nagios安装配置详解(图文)