如何优化 Map 遍历:优先使用 entrySet 而非 keySet

老明同学_6484

老明同学_6484

2026-01-18

676人浏览

原创

如何优化 Map 遍历:优先使用 entrySet 而非 keySet

遍历 map 时,若需同时访问键与值,应直接使用 `entryset()` 迭代而非 `keyset()` 加 `get()`,避免重复哈希查找,提升性能并消除 sonarqube 的 rspec-2864 代码异味警告。

在 Java 开发中,Map 是高频使用的集合类型。但一个常见却容易被忽视的性能陷阱是:仅通过 keySet() 遍历,再在循环体内反复调用 map.get(key) 获取对应值。这种写法看似直观,实则隐含冗余开销——每次 get() 都会重新执行哈希计算、桶定位与键比对(尤其在 HashMap 中),时间复杂度虽为平均 O(1),但常数因子显著增加;在大容量或高频调用场景下,性能损耗可被量化。

更优解是使用 map.entrySet():它返回 Set>,其中每个 Entry 封装了键值对的引用,直接通过 entry.getKey() 和 entry.getValue() 即可零成本获取二者,无需额外查找。

以原始代码为例:

// ❌ 低效:keySet + get → 每次循环触发一次哈希查找
for (String accounts : shiftDatesMap.keySet()) {
    Set<string> shiftDates = shiftDatesMap.get(accounts); // 不必要!
    // ... 后续逻辑
}</string>

应重构为:

Java 接口排错助手
Java 接口排错助手

在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。

下载
// ✅ 高效:entrySet 一次性获取键值对
for (Map.Entry<string set>> entry : shiftDatesMap.entrySet()) {
    String accounts = entry.getKey();
    Set<string> shiftDates = entry.getValue(); // 直接引用,无开销
    // ... 后续逻辑复用 accounts 和 shiftDates
}</string></string>

进一步结合您的业务逻辑(如匹配 Groups 并提取日期),完整优化示例如下:

public Set<date> getAccountShiftDate(Map<string set>> shiftDatesMap, List<groups> shiftSchedule) {
    Set<date> accountShiftDatesTemplate = new HashSet();

    for (Map.Entry<string set>> entry : shiftDatesMap.entrySet()) {
        String accounts = entry.getKey();
        Set<string> shiftDates = entry.getValue();

        Optional<groups> shiftOptional = shiftSchedule.stream()
            .filter(g -> StringUtils.equalsIgnoreCase(accounts, g.getLongName()))
            .findFirst();

        if (shiftOptional.isPresent()) {
            // 假设此处从 shiftDates 或 Groups 中解析 Date 并添加到结果集
            // accountShiftDatesTemplate.addAll(parseDates(shiftDates));
        }
    }
    return accountShiftDatesTemplate;
}</groups></string></string></date></groups></string></date>

⚠️ 注意事项:

  • 此优化仅在循环内需访问值(或键+值)时生效;若仅需键(如做存在性校验),keySet() 仍合理;
  • entrySet() 返回的是 Map 内部结构的视图,修改 Entry 的值(如 entry.setValue(...))可能影响原 Map(取决于具体实现,HashMap 支持);
  • 使用增强 for 循环时,确保 Map 非 null;若可能为空,建议提前判空或使用 Objects.requireNonNull();
  • SonarQube 规则 RSPEC-2864 的本质是鼓励“一次定位,多次利用”,这既是性能实践,也是代码可读性与意图清晰性的体现。

总结:将 keySet() 迭代升级为 entrySet(),是 Java Map 遍历的黄金准则之一——它用一行代码的微小改动,换来确定性的性能收益与静态分析合规性,值得在所有审查清单中置顶。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

549

3

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

2024.03.01

1698

6

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

2025.09.05

650

5

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

2025.11.16

343

7

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

2025.11.17

533

20

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

2025.11.27

303

6

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

2026.10.28

60

16

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

2026.10.28

40

15

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

2026.10.28

140

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习