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的循环姿势有哪几种?相关推荐

  1. 的 while循环_十八、Python图解while循环

    人生苦短,要学Python Python中循环有while循环和for循环,接下来将介绍Python中的while循环和for循环. while循环 语法格式 # while语句用于循环执行程序,也就 ...

  2. 跳出多重循环_代码里的俄罗斯套娃 | 07 多重循环

    点击上方 蓝字 关注我们 前情提要:刚上二年级的小红正在学习九九乘法表,老师说明天上课时要抽查,但她总是记不熟,你能写个程序帮帮她吗? 是不是想到了我们上一期学的For循环遍历,刚好可以用上.但好像又 ...

  3. shell脚本for循环_了解Shell脚本中的for循环

    shell脚本for循环 Continuing on from our previous tutorials, let's understand the for loop in shell scrip ...

  4. django中的for循环_深入了解 JavaScript 中的 for 循环

    在ECMAScript5(简称 ES5)中,有三种 for 循环,分别是: 简单for循环 for-in forEach 在2015年6月份发布的ECMAScript6(简称 ES6)中,新增了一种循 ...

  5. vba循环通过键盘某个按键按下退出循环_[VBA]For Next与Do Loop循环

    " 在黑夜中前行,行也寂寞,停也寂寞 " (更文的时候,正好最近发生许多事,算是做个自我安慰吧) 作为VBA的基本语句,For Next和Do Loop都是很早进入初学者学习的循环 ...

  6. python并发循环_在Python中模拟一个并发循环?

    在Python中模拟一个并发循环? 我需要模拟Python程序中的并发循环.不幸的是,以下简单的代码不起作用:list_of_ints = [ 1, 2, 3 ]iterator = list_of_ ...

  7. python种颜色循环_使用matplotlib颜色图进行颜色循环 - python

    如果我通过以下方式创建颜色: 将numpy导入为np 从matplotlib导入pyplot作为plt n = 6 color = plt.cm.coolwarm(np.linspace(0.1,0. ...

  8. java 暂停循环_在用于暂停线程时,循环Thread.Sleep()会不会对性能造成影响?...

    有(或者已经有)很多关于使用 Thread.Sleep() 方法的好坏的讨论 . 据我所知,它主要用于调试目的 . 现在我想知道:用于我的特定目的是不是很糟糕,也就是说,不断循环它以便能够暂停/恢复线 ...

  9. python读取二进制数据中的while循环_在Python中读取二进制文件并循环遍历每个字节...

    f = open("myfile", "rb") try: byte = f.read(1) while byte != "": # Do ...

最新文章

  1. VS Code竟然能约会,找对象不看脸,看编程水平
  2. Java中的异常和递归
  3. 安卓给string对象赋值_String 面试题!看完让你恍然大悟!
  4. Cropper – 简单的 jQuery 图片裁剪插件
  5. 引入 javascript_在您JavaScript项目中引入类型安全性? 再想一想
  6. IBM 发布企业级社交协作平台 Domino V10,开启快速应用程序开发的新时代
  7. C++中typedef void(*F)(类型)解读
  8. 获取键盘上某键的状态
  9. ae怎么输入竖排文字? ae文字竖排的方法
  10. 能量换算,方便减肥控制饮食
  11. Blender 建模
  12. 117. 请简述文本文件和二进制文件的区别
  13. dcdc模块降额设计_爱默生网络能源PCB设计规范
  14. Java接口的基本概念详解
  15. 如何快速推广引流?利用微博截流疯狂获取流量
  16. 雨听 | 英语学习笔记(十二)~作文范文:成绩与能力
  17. 欧几里得算法和扩展欧几里得算法——杨子曰数学
  18. windows系统DOS窗口
  19. VSCODE 使用One Dark Pro并优化
  20. STM32与SYN6288语音合成模块的使用

热门文章

  1. Linux学习总结(67)——shell脚本中$0 $1 $# $@ $* $? $ 等总结
  2. Json学习总结(8)——经过多方调研,最终还是决定禁用FastJson
  3. Mysql学习总结(48)——MySql的日志与备份还原
  4. Java基础学习总结(53)——HTTPS 理论详解与实践
  5. Java基础学习总结(32)——Java项目命名规范
  6. Maven学习总结(4)——Maven核心概念
  7. html表格中加横线,表格下划线怎么打出来
  8. char(128) mysql_char能表示(-128~127)
  9. php自学目录,PHP学习笔记(二) 了解PHP的基本语法以及目录结构
  10. CentOS6.5下的Nagios安装配置详解(图文)