Java中Map遍历的九种方式汇总

作者:zi-you 时间:2023-05-02 21:57:27 

日常工作中 Map 绝对是我们 Java 程序员高频使用的一种数据结构,那 Map 都有哪些遍历方式呢?这篇文章阿粉就带大家看一下,看看你经常使用的是哪一种。

通过 entrySet 来遍历

1、通过 formap.entrySet() 来遍历

第一种方式是采用 forMap.Entry 的形式来遍历,通过遍历 map.entrySet() 获取每个 entrykeyvalue,代码如下。这种方式一般也是阿粉使用的比较多的一种方式,没有什么花里胡哨的用法,就是很朴素的获取 map 的 keyvalue

public static void testMap1(Map<Integer, Integer> map) {
   long sum = 0;
   for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
     sum += entry.getKey() + entry.getValue();
   }
   System.out.println(sum);
 }

看过 HashMap 源码的同学应该会发现,这个遍历方式在源码中也有使用,如下图所示,

Java中Map遍历的九种方式汇总

putMapEntries 方法在我们调用 putAll 方法的时候会用到。

Java中Map遍历的九种方式汇总

2、通过 forIteratormap.entrySet() 来遍历

我们第一个方法是直接通过 forentrySet() 来遍历的,这次我们使用 entrySet() 的迭代器来遍历,代码如下。

public static void testMap2(Map<Integer, Integer> map) {
   long sum = 0;
   for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {
     Map.Entry<Integer, Integer> entry = entries.next();
     sum += entry.getKey() + entry.getValue();
   }
   System.out.println(sum);
 }

3、通过 whileIteratormap.entrySet() 来遍历

上面的迭代器是使用 for 来遍历,那我们自然可以想到还可以用 while 来进行遍历,所以代码如下所示。

public static void testMap3(Map<Integer, Integer> map) {
   Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
   long sum = 0;
   while (it.hasNext()) {
     Map.Entry<Integer, Integer> entry = it.next();
     sum += entry.getKey() + entry.getValue();
   }
   System.out.println(sum);
 }

这种方法跟上面的方法类似,只不过循环从 for 换成了 while,日常我们在开发的时候,很多场景都可以将 forwhile 进行替换。2 和 3 都使用迭代器 Iterator,通过迭代器的 next(),方法来获取下一个对象,依次判断是否有 next

通过 keySet 来遍历

上面的这三种方式虽然代码的写法不同,但是都是通过遍历 map.entrySet() 来获取结果的,殊途同归。接下来我们看另外的一组。

4、通过 for 和 map.keySet() 来遍历

前面的遍历是通过 map.entrySet() 来遍历,这里我们通过 map.keySet() 来遍历,顾名思义前者是保存 entry 的集合,后者是保存 key 的集合,遍历的代码如下,因为是 key 的集合,所以如果想要获取 key 对应的 value 的话,还需要通过 map.get(key) 来获取。

public static void testMap4(Map<Integer, Integer> map) {
   long sum = 0;
   for (Integer key : map.keySet()) {
     sum += key + map.get(key);
   }
   System.out.println(sum);
 }

5、通过 forIteratormap.keySet() 来遍历

public static void testMap5(Map<Integer, Integer> map) {
   long sum = 0;
   for (Iterator<Integer> key = map.keySet().iterator(); key.hasNext(); ) {
     Integer k = key.next();
     sum += k + map.get(k);
   }
   System.out.println(sum);
 }

6、通过 whileIteratormap.keySet() 来遍历

public static void testMap6(Map<Integer, Integer> map) {
   Iterator<Integer> it = map.keySet().iterator();
   long sum = 0;
   while (it.hasNext()) {
     Integer key = it.next();
     sum += key + map.get(key);
   }
   System.out.println(sum);
 }

我们可以看到这种方式相对于 map.entrySet() 方式,多了一步 get 的操作,这种场景比较适合我们只需要 key 的场景,如果也需要使用 value 的场景不建议使用 map.keySet() 来进行遍历,因为会多一步 map.get() 的操作。

Java 8 的遍历方式

注意下面的几个遍历方法都是是 JDK 1.8 引入的,如果使用的 JDK 版本不是 1.8 以及之后的版本的话,是不支持的。

7、通过 map.forEach() 来遍历

JDK 中的 forEach 方法,使用率也挺高的。

public static void testMap7(Map<Integer, Integer> map) {
   final long[] sum = {0};
   map.forEach((key, value) -> {
     sum[0] += key + value;
   });
   System.out.println(sum[0]);
 }

该方法被定义在 java.util.Map#forEach 中,并且是通过 default 关键字来标识的,如下图所示。这里提个问题,为什么要使用 default 来标识呢?欢迎把你的答案写在评论区。

Java中Map遍历的九种方式汇总

8、Stream 遍历

public static void testMap8(Map<Integer, Integer> map) {
   long sum = map.entrySet().stream().mapToLong(e -> e.getKey() + e.getValue()).sum();
   System.out.println(sum);
 }

9、ParallelStream 遍历

public static void testMap9(Map<Integer, Integer> map) {
   long sum = map.entrySet().parallelStream().mapToLong(e -> e.getKey() + e.getValue()).sum();
   System.out.println(sum);
 }

这两种遍历方式都是 JDK 8Stream 遍历方式,stream 是普通的遍历,parallelStream 是并行流遍历,在某些场景会提升性能,但是也不一定。

测试代码

上面的遍历方式有了,那么我们在日常开发中到底该使用哪一种呢?每一种的性能是怎么样的呢?为此阿粉这边通过下面的代码,我们来测试一下每种方式的执行时间。

public static void main(String[] args) {
  int outSize = 1;
   int mapSize = 200;
   Map<Integer, Integer> map = new HashMap<>(mapSize);
   for (int i = 0; i < mapSize; i++) {
     map.put(i, i);
   }
   System.out.println("---------------start------------------");
   long totalTime = 0;
   for (int size = outSize; size > 0; size--) {
     long startTime = System.currentTimeMillis();
     testMap1(map);
     totalTime += System.currentTimeMillis() - startTime;
   }
   System.out.println("testMap1 avg time is :" + (totalTime / outSize));
// 省略其他方法,代码跟上面一致
}

为了避免一些干扰,这里通过外层的 for 来进行多次计算,然后求平均值,当我们的参数分别是 outSize = 1,mapSize = 200 的时候,测试的结果如下

Java中Map遍历的九种方式汇总

Java中Map遍历的九种方式汇总

当随着我们增大 mapSize 的时候,我们会发现,后面几个方法的性能是逐渐上升的。

Java中Map遍历的九种方式汇总

Java中Map遍历的九种方式汇总

来源:https://www.cnblogs.com/zi-you/p/16920311.html

标签:Java,Map遍历
0
投稿

猜你喜欢

  • C#设置页面单位和缩放的方法

    2023-06-09 12:59:27
  • SpringBoot内置tomcat启动原理详解

    2021-11-02 19:32:33
  • c#中虚函数的相关使用方法

    2022-10-25 05:44:53
  • java 优雅关闭线程池的方案

    2022-03-20 23:05:44
  • C#多线程系列之线程完成数

    2021-12-24 03:07:47
  • Spring Security使用Lambda DSL配置流程详解

    2021-12-23 19:20:32
  • OpenCV实现人脸识别简单程序

    2023-07-07 00:31:12
  • 解决Mybatis 大数据量的批量insert问题

    2023-09-08 13:59:40
  • 详解C#设置Excel数据自适应行高、列宽的2种情况

    2022-10-21 23:46:29
  • C#读取csv格式文件的方法

    2023-08-28 22:38:46
  • 深入理解Java设计模式之代理模式

    2022-01-14 07:42:00
  • JAVA心得分享---return语句的用法

    2023-04-14 11:52:54
  • 极简的Resty服务端和客户端RESTful框架

    2022-01-19 19:51:00
  • c#中值类型和引用类型的基础教程

    2021-10-20 18:03:41
  • Java数据结构之实现哈希表的分离链接法

    2023-09-06 04:50:17
  • Android Studio中debug功能详解

    2022-05-22 08:16:01
  • Java面向对象程序设计:继承,多态用法实例分析

    2021-08-03 06:54:04
  • C#调用易语言写的Dll文件方法

    2023-07-21 01:56:10
  • 解决bufferedReader.readLine()读到最后发生阻塞的问题

    2022-07-15 06:05:38
  • Android圆形旋转菜单开发实例

    2023-09-06 11:42:52
  • asp之家 软件编程 m.aspxhome.com