如何使用Java 8 Streams找出字符串中出现最频繁的单词?
使用Java 8 Streams API找出重复次数最多的单词(忽略大小写)
给定输入字符串:
"Ram is employee of ABC company, ram is from Blore, RAM! is good in algorithms."
需要忽略大小写和标点符号统计单词出现次数,输出出现次数最多的单词及其次数,预期输出:
Ram -->3
is -->3
实现思路
- 提取有效单词:用正则表达式匹配字符串里的所有单词,自动跳过逗号、感叹号这类标点符号。
- 保留单词原始写法:把每个单词转成小写作为键,对应的第一次出现的原始单词作为值存起来,确保输出时能保留输入里的大小写样式。
- 统计单词出现次数:忽略大小写统计,比如Ram、ram、RAM会被算作同一个单词。
- 获取最高出现次数:从统计结果里找出次数最多的那个数值。
- 筛选并输出结果:把次数等于最大值的单词筛选出来,结合之前存的原始写法输出最终结果。
完整代码实现
import java.util.*; import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; public class MostFrequentWords { public static void main(String[] args) { String input = "Ram is employee of ABC company, ram is from Blore, RAM! is good in algorithms."; // 提取所有单词(匹配字母数字组成的完整单词) Pattern wordPattern = Pattern.compile("\\b\\w+\\b"); List<String> words = wordPattern.matcher(input).results() .map(matchResult -> matchResult.group()) .collect(Collectors.toList()); // 建立小写单词到首次出现的原单词的映射 Map<String, String> originalWordMap = words.stream() .collect(Collectors.toMap( String::toLowerCase, Function.identity(), (existing, newWord) -> existing // 保留第一次出现的单词形式 )); // 统计每个单词(忽略大小写)的出现次数 Map<String, Long> wordCountMap = words.stream() .map(String::toLowerCase) .collect(Collectors.groupingBy( Function.identity(), Collectors.counting() )); // 获取最大出现次数 long maxFrequency = wordCountMap.values().stream() .max(Long::compare) .orElse(0L); // 筛选并输出结果 wordCountMap.entrySet().stream() .filter(entry -> entry.getValue() == maxFrequency) .forEach(entry -> System.out.println(originalWordMap.get(entry.getKey()) + " -->" + entry.getValue())); } }
代码说明
- 正则提取单词:
\\b\\w+\\b会匹配以单词边界分隔的字母数字序列,自动过滤掉标点符号。 - 原单词映射:
Collectors.toMap里的合并函数会保留第一次出现的单词形式,避免后续覆盖原始写法。 - 次数统计:通过
map(String::toLowerCase)统一转为小写,再用groupingBy结合counting()完成高效的次数统计。 - 结果筛选:用流的
filter方法挑出次数等于最大值的条目,结合原单词映射输出符合预期的结果。
内容的提问来源于stack exchange,提问作者dev007
相关产品推荐
相关产品推荐

