
本文详解如何在 Java 中通过字符串分割与 Map 操作,统计文本中各单词出现次数,涵盖传统循环、merge() 方法及 Stream API 三种实现方式,并附可运行示例与关键注意事项。
本文详解如何在 java 中通过字符串分割与 map 操作,统计文本中各单词出现次数,涵盖传统循环、`merge()` 方法及 stream api 三种实现方式,并附可运行示例与关键注意事项。
在 Java 开发中,统计一段文本中每个单词的出现频次是一个经典且实用的练习,常用于日志分析、文本处理或面试算法题。核心思路是:将字符串按空格切分为单词数组,遍历每个单词,并用 Map<String, Integer> 动态维护“单词→频次”的映射关系。
以下是三种渐进式优化的实现方案:
✅ 方案一:基础显式判断(适合初学者理解逻辑)
private static HashMap<String, Integer> countWords(final String text) {
HashMap<String, Integer> wordMap = new HashMap<>();
String[] words = text.split(" ");
for (String word : words) {
if (wordMap.containsKey(word)) {
wordMap.put(word, wordMap.get(word) + 1);
} else {
wordMap.put(word, 1);
}
}
return wordMap;
}⚠️ 注意:此写法需两次 Map 查找(containsKey() + get()),存在冗余;且未处理空字符串或首尾空格——实际应用中建议先调用 trim() 并过滤空串:Arrays.stream(text.trim().split("\s+")) 更健壮。
✅ 方案二:使用 Map.merge()(推荐,简洁高效)
private static Map<String, Integer> countWords(final String text) {
Map<String, Integer> wordMap = new HashMap<>();
for (String word : text.trim().split("\s+")) {
wordMap.merge(word, 1, Integer::sum);
}
return wordMap;
}merge(key, defaultValue, remappingFunction) 的语义清晰:若 key 不存在,则设为 defaultValue(即 1);若已存在,则用 remappingFunction(此处为 Integer::sum)合并旧值与新值。一次查找完成读-改-写,线程安全前提下性能更优。
立即学习“Java免费学习笔记(深入)”;
✅ 方案三:函数式风格(Stream API,一行逻辑)
private static Map<String, Integer> countWords(final String text) {
return Arrays.stream(text.trim().split("\s+"))
.filter(word -> !word.isEmpty()) // 增强鲁棒性
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.summingInt(w -> 1)
));
}该写法高度声明式,利用 groupingBy + summingInt 自动完成分组计数。注意需静态导入 Collectors.* 和 Function.*;同时建议添加 filter 防止空字符串干扰结果。
? 总结与最佳实践
- 始终预处理输入:使用 trim() 和正则 \s+ 替代固定 " ",以兼容制表符、多空格等;
- 类型声明优先接口:返回类型用 Map<String, Integer> 而非 HashMap,利于后期替换实现;
- 避免 null 风险:split() 结果可能含空串,务必过滤;
- 性能对比:小数据量差异不明显;大数据量下,merge() 和 Stream 在可读性与性能间取得更好平衡。
完整可运行示例可直接复制到 Main.java 中测试,输出如 {Hello=2, world=1, all=1},验证逻辑正确性。

















