遍历 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() 即可零成本获取二者
,无需额外查找。
以原始代码为例:
应重构为:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
进一步结合您的业务逻辑(如匹配 Groups 并提取日期),完整优化示例如下:
⚠️ 注意事项:
此优化
仅在循环内需访问值(或键+值)时生效
;若仅需键(如做存在性校验),keySet() 仍合理;
entrySet() 返回的是 Map 内部结构的视图,修改 Entry 的值(如 entry.setValue(...))可能影响原 Map(取决于具体实现,HashMap 支持);
使用增强 for 循环时,确保 Map 非 null;若可能为空,建议提前判空或使用 Objects.requireNonNull();
SonarQube 规则 RSPEC-2864 的本质是鼓励“一次定位,多次利用”,这既是性能实践,也是
代码可读性
与意图清晰性的体现。
总结:将 keySet() 迭代升级为 entrySet(),是 Java Map 遍历的黄金准则之一——它用一行代码的微小改动,换来确定性的性能收益与静态分析合规性,值得在所有审查清单中置顶。
// ❌ 低效:keySet + get → 每次循环触发一次哈希查找
for (String accounts : shiftDatesMap.keySet()) {
Set shiftDates = shiftDatesMap.get(accounts); // 不必要!
// ... 后续逻辑
} // ✅ 高效:entrySet 一次性获取键值对
for (Map.Entry> entry : shiftDatesMap.entrySet()) {
String accounts = entry.getKey();
Set shiftDates = entry.getValue(); // 直接引用,无开销
// ... 后续逻辑复用 accounts 和 shiftDates
} public Set getAccountShiftDate(Map> shiftDatesMap, List shiftSchedule) {
Set accountShiftDatesTemplate = new HashSet<>();
for (Map.Entry> entry : shiftDatesMap.entrySet()) {
String accounts = entry.getKey();
Set shiftDates = entry.getValue();
Optional shiftOptional = shiftSchedule.stream()
.filter(g -> StringUtils.equalsIgnoreCase(accounts, g.getLongName()))
.findFirst();
if (shiftOptional.isPresent()) {
// 假设此处从 shiftDates 或 Groups 中解析 Date 并添加到结果集
// accountShiftDatesTemplate.addAll(parseDates(shiftDates));
}
}
return accountShiftDatesTemplate;
} 