当前位置: 首页 > news >正文

【Java】HashMap 的遍历方式有哪些?哪种更高效?

HashMap的遍历方式有很多种,常见的包括基于KeySet、entrySet、values、Java8+的forEach。以及迭代器Iterator等。

一、常见的遍历方式及示例:

1.通过keySet()遍历(键->值)。

KeySet()会返回所有的key的集合,遍历key后通过get(key)获取对应的value。

示例:

HashMap<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);// 遍历 key,再获取 value
for (String key : map.keySet()) {Integer value = map.get(key);System.out.println("key: " + key + ", value: " + value);
}

2.通过entrySet()遍历 (键值对直接获取):

entrySet()返回所有的键值对(Map.Entry)的集合,每个Entry对象同时包含key和value,可直接获取。

for (Map.Entry<String, Integer> entry : map.entrySet()) {String key = entry.getKey();Integer value = entry.getValue();System.out.println("key: " + key + ", value: " + value);
}

3.通过values()遍历(仅遍历值)

values()仅返回所有的value的集合,适合只需要value的场景。

for (Integer value : map.values()) {System.out.println("value: " + value);
}

4.Java8+forEach遍历(结合Lambda):

Java 8为Map新增了forEach方法,可直接通过Lambda表达式遍历键值对,代码更简洁。

map.forEach((key, value) -> {System.out.println("key: " + key + ", value: " + value);
});

5.迭代器Iterator遍历:

// 迭代 entrySet
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {Map.Entry<String, Integer> entry = iterator.next();System.out.println("key: " + entry.getKey() + ", value: " + entry.getValue());// 安全删除(需通过迭代器的 remove 方法)if (entry.getKey().equals("a")) {iterator.remove();}
}

二、效率对比:

  • entrySet()遍历效率>keySet()遍历效率。
  • Java 8+的forEachentrySet() 效率接近,但更简洁。

原因:

  • keySet() 遍历需要两步操作:先遍历key,再通过get(key)获取value。而get(key) 方法需要重新计算key的哈希值,定位桶位置,若存在哈希冲突,还需要遍历链表/红黑树查找,额外消耗性能。
  • entrySet()直接获取包含key和value的Entry对象,一次遍历即可同时拿到两者,无需额外的哈希计算和查找,减少了操作步骤,效率更高。
  • Java8的forEach方法内部基于entrySet()实现(源码中通过迭代entrySet完成),因此效率与entrySet()相当,但代码更简洁。

适用场景:

  • 同时获取key和value:优先使用entrySet() 或 Java 8+ 的 forEach(推荐后者,代码更简洁)。
  • 仅需 value:使用 values()。
  • 若需在遍历中删除元素,使用Iterator遍历entrySet(通过 iterator.remove() 安全删除,避免并发修改异常)

总结:

  • HashMap遍历的高效方式是entrySet() 或 Java 8+ 的 forEach,其中 forEach 兼具效率和简洁性,首选。
  • keySet() 因额外的 get 操作,效率较低,不推荐优先使用。
http://www.lryc.cn/news/612683.html

相关文章:

  • 什么是键值缓存?让 LLM 闪电般快速
  • OpenCV的关于图片的一些运用
  • 数据分析进阶——53页跨境数据分析【附全文阅读】
  • 僵尸进程问题排查
  • Mac+Chrome滚动截图
  • localforage的数据仓库、实例、storeName和name的概念和区别
  • OpenAI 开源模型 gpt-oss 正式上线微软 Foundry 平台
  • [Oracle] CEIL()函数
  • 利用微软SQL Server数据库管理员(SA)口令为空的攻击活动猖獗
  • MySQL中的DDL(一)
  • 直连微软,下载速度达18M/S
  • [2402MT-A] Redbag
  • 从周末去哪儿玩到决策树:机器学习算法的生活启示
  • 《深入解析缓存三大难题:穿透、雪崩、击穿及应对之道》
  • Mysql数据仓库备份脚本
  • 突破距离桎梏:5G 高清视频终端如何延伸无人机图传边界
  • 【完整源码+数据集+部署教程】无人机自然场景分割系统源码和数据集:改进yolo11-RVB
  • 计算机网络1-4:计算机网络的定义和分类
  • 【网络编程】一请求一线程
  • 云原生安全挑战与治理策略:从架构思维到落地实践
  • PyTorch + PaddlePaddle 语音识别
  • 从BaseMapper到LambdaWrapper:MyBatis-Plus的封神之路
  • day44 力扣1143.最长公共子序列 力扣1035.不相交的线 力扣53. 最大子序和 力扣392.判断子序列
  • WEB开发-第二十七天(PHP篇)
  • 笔试——Day31
  • Linux(17)——Linux进程信号(下)
  • 【42】【OpenCV C++】 计算图像某一列像素方差 或 某一行像素的方差;
  • uniapp vue3中使用pinia 和 pinia持久化(没有使用ts)
  • SQLite 创建表
  • VUE+SPRINGBOOT从0-1打造前后端-前后台系统-文章列表