
本文介绍如何使用 Java 8 的 Stream API 和传统循环两种方式,将形如 "20232,20221,..." 的年月编码字符串解析为 Map,其中 key 为 4 位年份,value 为去重、升序、逗号分隔的月份字符串。
本文介绍如何使用 java 8 的 stream api 和传统循环两种方式,将形如 `"20232,20221,..."` 的年月编码字符串解析为 `map
在 Java 应用中,常需处理紧凑编码的时间字符串(如 "20232" 表示 2023 年 2 月)。本教程提供两种健壮、可读性强的实现方案:一种是函数式风格的 Stream + Collectors 组合,另一种是清晰易懂的传统迭代方式。两者均确保:
✅ 年份提取准确(前 4 位字符)
✅ 月份提取鲁棒(剩余部分自动转为 Integer,兼容 10/11/12 等多位数)
✅ 同一年份下的月份自动去重、升序排列
✅ 最终 value 为逗号分隔的标准字符串(无尾随逗号)
✅ 推荐方案:Stream API(简洁高效)
String str = "20232,20221,20222,20223,20224,20225,20226,20227,20228,20229,202210,202211,202212,20231";
// 步骤 1:按年分组,值为 TreeSet<integer>(天然升序+去重)
Map<string set>> yearToMonths = Arrays.stream(str.split(","))
.collect(Collectors.groupingBy(
s -> s.substring(0, 4), // key: 年份(String)
Collectors.mapping(
s -> Integer.parseInt(s.substring(4)), // 提取并转为 Integer
Collectors.toCollection(TreeSet::new) // 自动升序、去重
)
));
// 步骤 2:转换为最终 Map<string string>
Map<string string> result = yearToMonths.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().stream()
.map(String::valueOf)
.collect(Collectors.joining(","))
));
// 输出结果
result.forEach((year, months) ->
System.out.println("[Key] : " + year + " [Value] : " + months));</string></string></string></integer>
输出:
[Key] : 2023 [Value] : 1,2 [Key] : 2022 [Value] : 1,2,3,4,5,6,7,8,9,10,11,12
✅ 兼容方案:传统 for 循环(适合初学者)
Map<string set>> yearToMonths = new HashMap();
Map<string string> result = new HashMap();
String[] parts = str.split(",");
for (String part : parts) {
String year = part.substring(0, 4);
int month = Integer.parseInt(part.substring(4)); // 自动处理 "10"/"12" 等
yearToMonths.computeIfAbsent(year, k -> new TreeSet()).add(month);
}
// 构建最终字符串值
for (Map.Entry<string set>> entry : yearToMonths.entrySet()) {
StringJoiner joiner = new StringJoiner(",");
for (int month : entry.getValue()) {
joiner.add(String.valueOf(month));
}
result.put(entry.getKey(), joiner.toString());
}</string></string></string>
? 关键技巧说明:
JavaStoryDevelop下载你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 使用 computeIfAbsent 替代手动 containsKey 判断,代码更简洁;
- StringJoiner 比 StringBuilder 更安全——无需手动处理分隔符边界;
- TreeSet 保证插入即排序,避免后续调用 Collections.sort()。
⚠️ 注意事项
- 输入校验:生产环境建议添加 null 或空字符串检查,以及 substring 越界防护(例如 part.length()
- 性能考量:对于超大数据量(>10 万项),Stream 方案因对象创建略高开销,但可读性与维护性优势显著;
- 扩展性:若需支持 ISO 格式(如 "2023-02"),只需调整 substring 逻辑为正则匹配或 DateTimeFormatter 解析。
通过以上任一方案,你都能高效、准确地完成年月字符串到结构化 Map 的转换,为后续统计、筛选或前端展示提供坚实的数据基础。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











