Map遍历方式有哪些(Java中9种Map遍历方式详解)

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

通过entrySet来遍历

1、通过for和map.entrySet()来遍历

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

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 源码的同学应该会发现,这个遍历方式在源码中也有使用,如下图所示,

Map遍历方式有哪些(Java中9种Map遍历方式详解)

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

Map遍历方式有哪些(Java中9种Map遍历方式详解)

2、通过for,Iterator和map.entrySet()来遍历

我们第一个方法是直接通过 for 和 entrySet() 来遍历的,这次我们使用 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、通过while,Iterator和map.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,日常我们在开发的时候,很多场景都可以将 for 和 while 进行替换。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、通过for,Iterator和map.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、通过while,Iterator和map.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 来标识呢?欢迎把你的答案写在评论区。

Map遍历方式有哪些(Java中9种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 8 的 Stream 遍历方式,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 的时候,测试的结果如下

Map遍历方式有哪些(Java中9种Map遍历方式详解)
Map遍历方式有哪些(Java中9种Map遍历方式详解)

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

Map遍历方式有哪些(Java中9种Map遍历方式详解)
Map遍历方式有哪些(Java中9种Map遍历方式详解)

总结

从上面的例子来看,当我们的集合数量很少的时候,基本上普通的遍历就可以搞定,不需要使用 JDK 8 的高级 API 来进行遍历,当我们的集合数量较大的时候,就可以考虑采用 JDK 8 的 forEach 或者 Stream 来进行遍历,这样的话效率更高。在普通的遍历方法中 entrySet() 的方法要比使用 keySet() 的方法好。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人,不代表IT壹频道。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。转载请注明出处:https://www.1pindao.com/baike/12174.html

(0)
上一篇 2022年 12月 2日 12:54:32
下一篇 2022年 12月 2日 12:59:57

相关推荐

  • Java多线程技术超详细(javaspring菜鸟教程)

    开头 Spring框架自诞生以来一直备受开发者青睐,有人亲切的称之为:Spring 全家桶。Spring更是 避免了重复造轮子的工作并跟随着互联网行业的发展做出不断的更新 ,很多研发人员把spring看作心目中最好的Java项目,没有之一。 可以毫不夸张的说,Spring重新定义了Java,所以这是重点也是难点,工作中必须会,面试时肯定考,不过很多人在面试的…

    2022年 12月 2日 百科知识
    249
  • pdf文件太大如何变小(免费缩小pdf文件大小的方法)

    在我们日常工作中,经常会给政府或者地方审核网站上传PDF,几乎它们都把PDF的大小限制的很小,比如600K内,300K以内等各种情况。 那我们怎么把PDF压缩到最小且不损失它的画质呢? 接下来有几种方法让我来教教你们: 第一种:我们先看一下原PDF有多大,达到了2.39M!在许多场合这么大的文件是无法上传的。 首先我们打开PDF,如果PDF内容为图片内容的,…

    2022年 12月 2日 百科知识
    268
  • 冤种是什么意思(一文读懂6个网络热词的含义)

    现在的网络热词真是越来越多啦,也是千奇百怪!今天小编带着大家再来认识一下这些网络热词吧,总有一个你特别熟悉的网络热词。 现在这时代不了解这些“网络热词”,都不好意思说自己是年轻人,今天给大家带来一组流行的网络词汇,一起来了解下吧: 芭比Q,在网络上,“芭比q”现在多用于表示“完蛋了”、“完了,没救了”的意思。这一句话经常出现在网络上一些非常古怪搞笑的,和一些…

    2022年 11月 24日 百科知识
    230
  • p2p技术是什么意思(简述p2p技术的原理及特点)

    文|顾旭光 来源|智能相对论(aixdlun) 近几天,诞生二十余年的P2P技术由于安全性问题又成为了业界和大众热议的话题。作为一种去中心化的下载技术,其伴随了大部分国内第一代网民的青春记忆,时至今日还有大量的“种子”爱好者沉醉在这项技术带来的“福利”中。 站在历史的角度看,下载技术的发展史基本就是一部网络发展史,从互联网诞生的那天,带宽决定着互联网产品的形…

    2023年 1月 15日 百科知识
    90
  • win10版本区别详解(windows10各个版本的区别)

    windows10各个版本的区别你知道吗? 微软在windows10发行时针对不同的使用群体提供不同的版本,这就使得我们在安装操作系统时要对版本进行选择了,因为不同的版本提供的功能是有区别的,比如说win10专业版提供组策略编辑入口,而家庭版就没有。那么win10各个版本具体都有哪些的区别呢?下面小编就给大家整理了一份,如果你的windows系统还没升级,那…

    2023年 1月 19日
    102
  • java分布式架构有哪些技术(java分布式和微服务的区别)

    分布式架构设计属于进阶Java架构师的必经之路,而且大厂也特别喜欢考察,建议大家需要重点掌握。 为了方便大家更好的掌握好分布式架构,也为了让知识更系统化,这里我单独把分布式架构的整个系列一并罗列于此,希望对有用的人有用,也希望能帮助到更多的人! 单点登录SSO的实现原理与方案详解 单点登录是分布式大型网站必备技术,例如淘宝、天猫、聚划算等网站,用户只需要登录…

    2022年 12月 17日 百科知识
    130