Java遍历Map效率对比

Java遍历Map效率对比Java中Map容器的遍历有多种方式,但是不同的方式效率会大有不同,以前没有注意这些细节,随意使用遍历方式在本地可能没有什么影响,但是在项目在高频使用需要特别注意,尽量使用高效的方式。首先,Map.Entry<K,V>是可以包含了Key和Value的,keySet包含了所有的Key,再使用get方法可以拿到对应的Value;所以包含Key和Value内容…

大家好,又见面了,我是你们的朋友全栈君。

Java遍历Map效率对比

Java 中Map容器的遍历有多种方式,但是不同的方式效率会大有不同,以前没有注意这些细节,随意使用遍历方式在本地可能没有什么影响,但是在项目在高频使用需要特别注意,尽量使用高效的方式。

首先,Map.Entry<K,V>是可以包含了Key和Value的,keySet包含了所有的Key,再使用get方法可以拿到对应的Value;所以包含Key和Value内容的就有两种方式,我们再看访问模式,可以使用迭代器Iterator 访问,也可以使用For循环访问;那么2种包含方式和访问模式组合起来就是4种访问方式

初始化Map

导入相应的包

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

我们选择不同规模Key记录来测试不同方式的差异

    Map<String, String> map = new HashMap<>();
    String key, value;
    int num = 10000; // num值从{1w, 10w, 100w, 1000w}中选择
    for (int i = 1; i <= num; i++) { 
   
      key = "mykey" + i;
      value = "myvalue" + i;
      map.put(key, value);
    }

keySet 与 Iterator

    long startTime1 =System.currentTimeMillis();
    Iterator<String> iter = map.keySet().iterator();
    while (iter.hasNext()){ 
   
      key=iter.next();
      value=map.get(key);
    }
    long endTime1 =System.currentTimeMillis();
    System.out.println("Run:"+(endTime1-startTime1)+"ms KeySet && Iterator");

keySet 与 for-loop

    long startTime2 =System.currentTimeMillis();
    for(String key2:map.keySet()){ 
   
      value=map.get(key2);
    }
    long endTime2 =System.currentTimeMillis();
    System.out.println("Run:"+(endTime2-startTime2)+"ms KeySet && For-Loop");

Map.Entry<K,V> 与 Iterator

    long startTime3=System.currentTimeMillis();
    Iterator<Map.Entry<String,String>> iter3 =map.entrySet().iterator();
    Map.Entry<String,String> entry3;
    while (iter3.hasNext()){ 
   
      entry3 = iter3.next();
      key = entry3.getKey();
      value=entry3.getValue();
    }
    long endTime3 =System.currentTimeMillis();
    System.out.println("Run:" +(endTime3-startTime3)+"ms Map.Entry && Iterator");

Map.Entry<K,V> 与 for-loop

    long startTime4=System.currentTimeMillis();
    for(Map.Entry<String,String> entry4:map.entrySet()){ 
   
      key=entry4.getKey();
      value=entry4.getValue();
    }
    long endTime4 =System.currentTimeMillis();
    System.out.println("Run:"+(endTime4-startTime4) +"ms Map.Entry && For-Loop");

效率比较

以下运行时间单位为毫秒(ms)

Key数量 Entry && Iterator Entry && For-Loop KeySet && Iterator KeySet && For-Loop
10000(1w) 2 1 3 2
100000(10w) 8 6 10 8
1000000(100w) 38 32 39 36
10000000(1000w) 236 251 316 319

对比结论

多次验证,上述结果变化基本不大。使用Map.Entry<K,V>与for循环的组合是最有效率的

Map常用方法

Set<K> keySet()
Collection<V> values()
V get(Object key)
boolean containsKey(Object key)
boolean containsValue(Object value)
V getOrDefault(Object key, V defaultValue)

Java8 Map的遍历使用了新的方式forEach,这个函数就非常方便了,但是forEach中的值k,v是不可变的,在Java中是final的,这样就无法将k,v赋值给外部的变量了。如果一定要修改外部的值,需要用一个初值来累加/减/乘/除等操作

    Map<String, String> map = new HashMap<>();
    String key, value;
    int num = 10;
    for (int i = 1; i <= num; i++) { 
   
      key = "mykey" + i;
      value = "myvalue" + i;
      map.put(key, value);
    }

    map.forEach((k, v) -> { 
     // 非常方便
      System.out.println(k + ":" + v);
    });

把一个Map全部放到另外一个Map中

void putAll(Map<? extends K,? extends V> m)

删除一个键值对

boolean remove(Object key)

替换一个键值对

boolean	replace(K key, V oldValue, V newValue)

替换Map中所有Entry的value值,这个值由旧的key和value计算得出

void replaceAll(BiFunction<? super K,? super V,? extends V> function)

参考

  1. Map-Javadoc
  2. Map遍历效率比较
  3. 遍历HashMap的几种方式及其效率比较,HashMap删除元素时如何处理
  4. Java中HashMap的四种遍历方法,及效率比较
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/126148.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • VS Code 必备插件推荐「建议收藏」

    VS Code 必备插件推荐「建议收藏」插件说明备注AutoCloseTag自动添加HTML/XML关闭标签AutoRenameTag自动重命名配对的HTML/XML标签Beautify格式化代码BracketPairColorizer颜色识别匹配括号CodeRunner非常强大的一款插件…

  • 动态规划——背包问题(详解)

    动态规划——背包问题(详解)动态规划是我最早接触的算法,一开始非常简单,固定模板题,后来愈发愈发难起来了,条件,状态压缩等等,难点主要是,状态怎么表示,状态转移方程怎么写,这篇文章将会从背包五大问题详解,希望能帮助到大家去类比,思考其他动态规划题目。首先先来看看动态规划的定义:动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。

  • 频谱分析仪的基本使用方法_频谱仪的功能使用

    频谱分析仪的基本使用方法_频谱仪的功能使用因为项目需要,今天学着使用的一下频谱分析仪,项目属于物联网类型,通信方式是使用的当前市面上比较火的Lora技术(当前市面上常用的两种低功耗远距离通信方案是LORA和NB-LOT)。本次使用频谱分析仪用来测量设计的板子用Lora发送无线数据时候的一些相关参数,主要测试天线发送数据时候的发射功率(单位:DB)。在这里对仪器的基本使用做一个记录,以为备忘。一、频谱分析仪的使用入门如下图为所使

  • smalldatetime

    smalldatetimeSQLSERVER的DateTime类型精度很高,精确到秒再往下,对于一般的系统,完全没有必要,因此日期类型,我通常设置为smalldatetime,精确到分就行了,它的秒恒为0。但今天才知道,它的日期有范围,是1900-01-01到2079-06-06所以象下面这种句子就一定会报错:declare@dateSMALLDATETIME=’2099-01-01’DATETIME:17

  • 关于UDP接收icmp端口不可达(port unreachable)

    关于UDP接收icmp端口不可达(port unreachable)本篇分为3部分1:报文格式2:产生的原因3:linux协议栈如何处理4:应用层如何获取1:报文如下,10.30.13.1往10.30.16.10的80端口发送了一个UDP报文,80端口其实监听的是TCP。服务器回复了一个类型为端口不可达的ICMP,ICMP数据部分就是请求UDPip层及其以上的数据。2:原因首先原因就是接收udp报文…

  • Qt编写安防视频监控系统1-通道切换

    Qt编写安防视频监控系统1-通道切换一、前言通道切换在视频监控系统中是最基础的必备功能,一般都会提供1通道+4通道+6通道+8通道+9通道+16通道这几个通道切换,可能做得比较好的还会提供24通道+32通道的,这个可能对电脑的配置就有一定要求了,一般来说,超过9个通道实时显示视频流,基本上会采用子码流来显示,如果都采用主码流,电脑压力非常巨大,CPU占用很高,内存也高,不过现在的电脑配置越来越高,基本上四千多的台式机,配置已经非常…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号