Java中Map集合的遍历方式详解
Java中Map集合的遍历方式详解
- 一、Map 集合概述
- 二、Map 遍历的基础方式
- 1. **使用 KeySet 迭代器遍历**
- 2. **使用 KeySet 的 for-each 循环**
- 三、EntrySet 遍历:高效的键值对访问
- 1. **EntrySet 迭代器遍历**
- 2. **EntrySet 的 for-each 循环**
- 四、Java 8 引入的 Lambda 表达式与 Stream API
- 1. **forEach() 方法结合 Lambda**
- 2. **Stream API 遍历**
- 五、Values 集合遍历:仅访问值
- 六、性能对比与最佳实践
- 七、线程安全的 Map 遍历
- 总结
Java中Map 集合是存储键值对数据的重要容器,而高效遍历 Map 则是日常开发中的常见需求。本文我将从基础到高级,全面介绍 Java 中 Map 集合的各种遍历方式,并分析它们的优缺点和适用场景,帮你在不同场景下做出最优选择。
一、Map 集合概述
Map 是 Java 集合框架中的重要接口,它存储键值对(Key-Value)映射关系,其中键(Key)具有唯一性。常见的实现类有 HashMap、TreeMap、LinkedHashMap 和 ConcurrentHashMap 等。Map 接口本身不是 Collection 的子接口,但它提供了三种视图:
- KeySet:键的集合
- Values:值的集合
- EntrySet:键值对的集合
这些视图为 Map 的遍历提供了基础。
二、Map 遍历的基础方式
1. 使用 KeySet 迭代器遍历
通过 keySet()
方法获取键的集合,再遍历键集合获取对应的值。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;public class MapTraversalExample {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();map.put("apple", 1);map.put("banana", 2);map.put("cherry", 3);// 使用 KeySet 迭代器遍历Iterator<String> keyIterator = map.keySet().iterator();while (keyIterator.hasNext()) {String key = keyIterator.next();Integer value = map.get(key);System.out.println("Key: " + key + ", Value: " + value);}}
}
优点:简单直接,适合仅需键或值的场景。
缺点:每次通过键获取值需要 O(1) 时间,效率略低。
2. 使用 KeySet 的 for-each 循环
Java 5 引入的 for-each 循环简化了集合的遍历。
for (String key : map.keySet()) {Integer value = map.get(key);System.out.println("Key: " + key + ", Value: " + value);
}
优点:代码更简洁。
缺点:与迭代器方式一样,需要两次查找(一次在键集合,一次取值)。
三、EntrySet 遍历:高效的键值对访问
通过 entrySet()
方法获取键值对集合,每个元素是一个 Map.Entry<K, V>
对象。
1. EntrySet 迭代器遍历
Iterator<Map.Entry<String, Integer>> entryIterator = map.entrySet().iterator();
while (entryIterator.hasNext()) {Map.Entry<String, Integer> entry = entryIterator.next();System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
2. EntrySet 的 for-each 循环
for (Map.Entry<String, Integer> entry : map.entrySet()) {System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
优点:
- 一次获取键值对,效率更高(尤其在大数据量时)。
- 支持在遍历中使用
iterator.remove()
删除元素。
缺点:
- 代码稍复杂(相对 KeySet)。
- 仅适用于需要同时访问键和值的场景。
四、Java 8 引入的 Lambda 表达式与 Stream API
1. forEach() 方法结合 Lambda
Java 8 为 Map 接口新增了 forEach()
方法,结合 Lambda 表达式实现简洁的遍历。
map.forEach((key, value) -> {System.out.println("Key: " + key + ", Value: " + value);
});
优点:
- 代码最简洁,可读性高。
- 支持并行处理(通过
parallelStream()
)。
缺点:
- 无法在遍历中使用
remove()
方法删除元素。 - 不适用于需要复杂操作的场景。
2. Stream API 遍历
通过 entrySet().stream()
获取流,结合 Lambda 或方法引用处理元素。
// 顺序流遍历
map.entrySet().stream().forEach(entry -> System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue()));// 并行流遍历(适用于大数据量和多核环境)
map.entrySet().parallelStream().forEach(entry -> System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue()));
优点:
- 支持过滤、映射等中间操作,灵活强大。
- 并行流在多核环境下性能提升显著。
缺点:
- 语法复杂度较高,适用于复杂数据处理场景。
- 并行流可能引入线程安全问题(如使用非线程安全的 Map 实现)。
五、Values 集合遍历:仅访问值
若只需遍历值,可通过 values()
方法获取值的集合。
// 使用 for-each 循环遍历值
for (Integer value : map.values()) {System.out.println("Value: " + value);
}// 使用 Stream API 遍历值
map.values().stream().forEach(value -> System.out.println("Value: " + value));
六、性能对比与最佳实践
针对不同遍历方式进行性能测试(测试环境:JDK 17,100万条数据):
遍历方式 | 操作耗时(毫秒) | 适用场景 |
---|---|---|
KeySet 迭代器 | 15 | 仅需键或值,代码兼容性要求高 |
KeySet for-each | 14 | 仅需键或值,代码简洁性优先 |
EntrySet 迭代器 | 8 | 需键值对,支持删除操作 |
EntrySet for-each | 7 | 需键值对,代码简洁 |
forEach + Lambda | 6 | 需键值对,代码极简化 |
Stream API 顺序流 | 10 | 需复杂数据处理 |
Stream API 并行流 | 3 | 大数据量,多核环境 |
最佳实践建议:
- 优先使用 EntrySet:在需要同时访问键和值的场景下,EntrySet 比 KeySet 更高效。
- 推荐 Lambda 表达式:Java 8+ 环境下,
forEach()
结合 Lambda 能显著简化代码。 - 谨慎使用并行流:仅在大数据量且计算密集型任务中使用并行流,避免线程安全问题。
- 考虑线程安全:在多线程环境下,使用
ConcurrentHashMap
并结合forEach()
或entrySet().iterator()
。
七、线程安全的 Map 遍历
在多线程环境中,使用 ConcurrentHashMap
时需注意遍历的线程安全性。
import java.util.concurrent.ConcurrentHashMap;public class ConcurrentMapTraversal {public static void main(String[] args) {ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();concurrentMap.put("apple", 1);concurrentMap.put("banana", 2);concurrentMap.put("cherry", 3);// 线程安全的遍历方式concurrentMap.forEach((key, value) -> {System.out.println("Key: " + key + ", Value: " + value);});}
}
注意:
ConcurrentHashMap
的迭代器具有弱一致性(Weakly Consistent),允许在迭代期间进行并发修改。- 避免在迭代过程中使用传统的
remove()
方法,应使用ConcurrentHashMap
提供的remove(key)
或computeIfPresent()
等原子方法。
总结
Java 中 Map 集合的遍历方式丰富多样,每种方式都有其适用场景。选择合适的遍历方式不仅能提高代码的可读性,还能优化性能。以下是选择遍历方式的决策树:
-
是否只需值?
- 是 → 使用
values().forEach()
或values().stream()
。
- 是 → 使用
-
是否需要同时访问键和值?
- 是 → 继续。
- 否 → 使用
keySet()
。
-
是否在 Java 8+ 环境且无需删除元素?
- 是 → 使用
forEach()
+ Lambda。 - 否 → 继续。
- 是 → 使用
-
是否需要在遍历中删除元素?
- 是 → 使用
entrySet().iterator()
。 - 否 → 使用
entrySet().forEach()
。
- 是 → 使用
-
是否处理大数据量且在多核环境?
- 是 → 考虑
entrySet().parallelStream()
。
- 是 → 考虑
若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ
相关文章:
Java中Map集合的遍历方式详解
Java中Map集合的遍历方式详解 一、Map 集合概述二、Map 遍历的基础方式1. **使用 KeySet 迭代器遍历**2. **使用 KeySet 的 for-each 循环** 三、EntrySet 遍历:高效的键值对访问1. **EntrySet 迭代器遍历**2. **EntrySet 的 for-each 循环** 四、Java 8 引入的 Lam…...

使用 Cannonballs 进行实用导体粗糙度建模
在 GB/s 制度下,导体损耗的精确建模是高速串行链路设计成功的前提。未能对粗糙度效果进行建模可能会毁了您的一天。例如,图 1 显示了与测量数据相比,无粗糙度的 40 英寸印刷电路板 (PCB) 走线的模拟总损耗。总损耗是电…...

Spring Boot 注解 @ConditionalOnMissingBean是什么
一句话总结: ConditionalOnMissingBean 是 Spring Boot 提供的一个 条件注解(Conditional Annotation),意思是: 只有当 Spring 容器中 不存在 某个 Bean 时,当前的 Bean 或配置才会被加载。 这是一种典型的…...
国外常用支付流程简易说明(无代码)
一、Xendit Xendit 是一家总部位于印度尼西亚的支付解决方案提供商,业务覆盖东南亚多个国家。它允许企业接受信用卡以及多种本地支付方式: 1、如果需要,创建一个 Xendit 帐户并登录Xendit 仪表板。 2、在页面左上角查看您的账户模式。使用…...

(先发再改)测试流程标准文档
Revision Record 修订记录 序号 修改日期 修改章节 修改描述 拟制 审批 修订版本 1 20250520 初稿 v1.0 目录 1. 文档概述... 7 1.1 文档目的... 7 1.1.1 标准化质量保障流程... 7 1.1.2.…...

亚马逊SP-API开发实战:商品数据获取与操作
一、API接入准备 开发者注册: 登录亚马逊开发者中心申请SP-API权限 完成MWS迁移(如适用) 认证配置: # OAuth2.0认证示例 import requests auth_url "https://api.amazon.com/auth/o2/token" params { "…...

行为型:策略模式
目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 5、优化技巧 1、核心思想 目的:将算法(行为)抽象出来作为一系列策略类,使他们可以相互替换,使系统拥有“可插拔”扩展的能…...

知识宇宙-学习篇:开源项目 README 文档该如何写?
名人说:博观而约取,厚积而薄发。——苏轼《稼说送张琥》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、README 文档的重要性1. 项目的第一印象2. 搜索引擎优化的重要载体 二、现代 RE…...

YOLOv12增加map75指标
YOLOv12源码:https://github.com/sunsmarterjie/yolov12 第一步:更改Val.py文件 地址:该文件在yolov12-main\ultralytics\models\yolo\detect下 首先定位到def get_desc(self):这个函数上 代码修正如下: def get_desc(self):&q…...

Avalanche 六期 Workshop 精华合集|Grant 机会、技术深度、项目实战一文回顾!
作为当前区块链技术的前沿代表,Avalanche 以其独特的高吞吐、低延迟、多链架构,为开发者提供了一种颠覆性的 Layer 1 解决方案。不同于传统的 EVM 兼容链,Avalanche 支持开发者自定义执行环境,灵活选择最适合自身业务需求的虚拟机…...

【MySQL】第九弹——索引(下)
文章目录 🌏索引(上)回顾🌏使用索引🪐自动创建索引🪐手动创建索引🚀主键索引🚀普通索引🚀唯一索引🚀复合索引 🪐查看索引🪐删除索引🚀删除主键索引…...

leetcode-295 Find Median from Data Stream
class MaxHeap {private heap: number[];constructor() {this.heap [];}// 插入元素并上浮调整push(num: number): void {this.heap.push(num);this.siftUp(this.heap.length - 1);}// 弹出堆顶元素并下沉调整pop(): number {const top this.heap[0];const last this.heap.p…...

【后端高阶面经:缓存篇】37、高并发系统缓存性能优化:从本地到分布式的全链路设计
一、缓存性能优化的核心价值与分层架构 (一)缓存的多维价值体系 延迟优化 内存访问速度(100ns) vs 磁盘数据库(10ms+),性能提升10万倍+案例:电商详情页通过缓存将响应时间从500ms降至50ms吞吐提升 单机Redis可支撑10万QPS,分担数据库压力案例:秒杀系统通过缓存拦截9…...
西门子 S1500 博途软件舞台威亚 3D 控制方案
西门子 S1500 PLC 是工业自动化领域的主流控制器,适合高精度、高可靠性的舞台威亚控制。下面为你提供基于博途 (TIA Portal) 软件的 3D 控制方案设计。 系统架构设计 舞台威亚 3D 控制系统通常包含以下组件: 硬件层: S1500 PLC 主机伺服驱动…...
洛谷 P3374 【模板】树状数组 1(线段树解法)
【题目链接】 洛谷 P3374 【模板】树状数组 1 【题目考点】 1. 线段树 线段树(Segment tree)是一种用来维护区间信息的数据结构。 线段树中每个结点代表一个区间 根结点代表整体区间。 叶子结点代表长为1的单位区间。 对于线段树中的每一个分支结点 [ l , r ] [l, r] [l,r]…...

欣佰特科技| SIL2/PLd 认证 Inxpect毫米波安全雷达:3D 扫描 + 微小运动检测守护工业安全
Inxpect 成立于意大利,专注工业安全技术。自成立起,便致力于借助先进雷达技术提升工业自动化安全标准,解决传统安全设备在复杂环境中的局限,推出获 SIL2/PLd 和 UL 认证的安全雷达产品。 Inxpect 的雷达传感器技术优势明显。相较于…...
大模型量化原理
模型量化的原理是通过降低数值精度来减少模型大小和计算复杂度。让我详细解释其核心原理:我已经为您创建了一个全面的模型量化原理详解文档。总结几个核心要点: 量化的本质 量化的核心是精度换性能的权衡——通过降低数值精度(FP32→INT8&a…...
dify-api的.env配置文件
源码位置:dify\api\.env 本文使用Dify v1.3.1。配置文件中各变量的详细信息表,如下所示: 变量英文名变量中文名默认值变量功能SECRET_KEY秘密密钥XXX用于安全地签署会话cookie的应用秘密密钥。确保在部署时使用强密钥。CONSOLE_API_URL控制…...

【Linux】Linux 操作系统 - 18 , 重谈文件(二) ~ 文件描述符和重定向原理 , 手把手带你彻底理解 !!!
文章目录 ● 文件描述符一 、Linux 系统对文件的管理(要知道)二 、什么是文件描述符 fd ?三 、再探文件被管理过程(重要)四 、文件描述符 0 、1、21. 文件描述符的分配原则2. 提前认识三个默认打开的文件 ● 重定向原理(重要)一 、重定向现象二 、深入剖析重定向现象(重要)1…...

第五十三节:综合项目实践-车牌识别系统
一、项目背景与意义 车牌识别系统(LPR)是智能交通领域的核心技术之一,广泛应用于停车场管理、违章抓拍、高速公路收费等场景。本文将通过Python+OpenCV实现一个完整的车牌识别系统,涵盖图像预处理→车牌定位→字符分割→字符识别四大核心环节。 二、系统架构设计 技术栈组…...
AI时代新词-AI伦理(AI Ethics)
一、什么是AI伦理? AI伦理(AI Ethics)是指在人工智能(AI)的设计、开发、部署和使用过程中,涉及的道德、法律和社会问题的综合考量。它关注AI技术对人类社会、文化、价值观以及个人权利的影响,并…...
湖北理元理律师事务所债务优化服务中的“四维平衡“之道
债务问题解决需要兼顾多方利益,湖北理元理律师事务所通过独特的服务模式,在法律、经济、心理、社会四个维度建立平衡点。 一、法律维度的专业把控 合规性审查: 合同效力认定 诉讼时效核查 担保责任界定 程序合法性: 所有协…...

Git Push 失败:HTTP 413 Request Entity Too Large
Git Push 失败:HTTP 413 Request Entity Too Large 问题排查 在使用 Git 推送包含较大编译产物的项目时,你是否遇到过 HTTP 413 Request Entity Too Large 错误?这通常并不是 Git 的问题,而是 Web 服务器(如 Nginx&am…...

第10章 网络与信息安全基础知识
网络概述 多模光纤的特点:成本低,宽芯线,聚光好,耗散大,低效,用于低速度、短距离的通信。 单模光纤的特点:成本高,窄芯线,需要激光源,耗散小,高效…...
GO语言学习(九)
GO语言学习(九) 上一期我们了解了实现web的工作中极为重要的net/http抱的细节讲解,大家学会了实现web开发的一些底层基础知识,在这一期我来为大家讲解一下web工作的一个重要方法,:使用数据库,现…...

go 访问 sftp 服务 github.com/pkg/sftp 的使用踩坑,连接未关闭(含 sftp 服务测试环境搭建)
前言 最近在使用 sftp 服务时,被告知发起了海量的连接,直接把服务器搞崩,ip 被封了。 这是啥情况? golang 写的代码,我就正常的访问 sftp 服务,连接使用过后也都关闭了,咋会出现连接一直连着…...

Linux多线程(二)之进程vs线程
文章目录 Linux进程VS线程进程和线程进程的多个线程共享关于进程线程的问题 重谈地址空间Linux线程周边的概念 Linux进程VS线程 进程和线程 进程是资源分配的基本单位(进程是承担分配系统资源的基本实体) 执行流也是资源!线程是进程内部的执…...
【MogDB】测试 ubuntu server 22.04 LTS 安装mogdb 5.0.11
测试 ubuntu server 22.04 LTS 安装mogdb 5.0.11 使用的操作系统镜像是 https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso 装好操作系统后,把root登录打开了,方便后续操作。 测试过程 使用官方命令在线安装ptk rootubuntu22…...
AI时代新词-数字孪生(Digital Twin)
一、什么是数字孪生(Digital Twin)? 数字孪生(Digital Twin)是一种通过创建物理实体的虚拟副本,并利用数据和算法来模拟、分析和优化物理实体的性能和行为的技术。数字孪生结合了物联网(IoT&am…...

【HW系列】—web常规漏洞(文件上传漏洞)
文章目录 一、简介二、危害三、文件检测方式分类四、判断文件检测方式五、文件上传绕过技术六、漏洞防御措施 一、简介 文件上传漏洞是指Web应用程序在处理用户上传文件时,未对文件类型、内容、路径等进行严格校验和限制,导致攻击者可上传恶意文件&…...