. 编写 Java 程序统计一篇英文文档中各单词出现的次数,并按单词出现的 频率由高到低进行输出。 例如:文档“Hello word Hello”的统计结果为: Hello:2 次
时间: 2025-07-08 22:29:47 浏览: 3
<think>好的,我现在需要帮用户解决一个Java编程问题,统计英文文档中各单词出现的次数,并按频率从高到低输出。首先,我得理解用户的需求。用户给的例子是“Hello word Hello”,输出结果是Hello出现2次,word出现1次。看起来需要处理大小写吗?比如,如果文档里有“Hello”和“hello”,应该算作同一个单词还是不同的?这里用户没有特别说明,可能默认是不区分大小写的,但可能需要提醒用户注意这点。
接下来,我得考虑程序的步骤。首先,读取文档内容。用户可能希望从文件读取还是直接处理字符串?可能需要两种方式,但用户没有说明,所以假设是从文件读取。然后,需要将文档内容拆分成单词。拆分的时候要注意标点符号,比如“word,”和“word”应该算作同一个单词,所以需要去除标点,可能用正则表达式来分割非字母的字符。
然后是统计单词出现的次数。这里可以用HashMap来存储单词和对应的次数。遍历拆分后的单词数组,将每个单词转为小写(如果忽略大小写),然后放入HashMap中统计。接下来是排序,需要根据频率从高到低排序,所以需要将HashMap的entrySet转换成List,然后自定义比较器,按值降序排序。
最后是输出结果。遍历排序后的列表,输出单词和次数。需要注意的是,用户给的例子中输出是“Hello:2 次”,可能要保持原单词的大小写,但统计的时候是忽略大小写的。这里可能存在矛盾,比如原文中的“Hello”和“HELLO”会被统计为同一个单词,但输出时应该保留原样吗?用户例子中的输出保留了原单词的大小写,所以可能需要记录每个单词的原始形式,但统计时统一处理。不过这可能比较复杂,或者用户可能接受统一转为小写后统计,但输出时可能显示的是小写形式。需要进一步明确,但用户例子中的输出是保留原大小写的,比如“Hello”出现两次,而“word”出现一次,所以可能输入中的单词是区分大小写的。但例子中的输入是“Hello word Hello”,所以两个Hello是相同的,而word是另一个。可能用户希望区分大小写,所以统计时不需要转换大小写。这点需要确认,但用户没有说明,可能需要按照区分大小写来处理,或者在代码中让用户选择。不过为了简单起见,可能先按区分大小写处理,除非用户有特别说明。
那回到步骤,首先读取文档内容,可能用BufferedReader读取文件。然后,用正则表达式分割单词,比如使用split("[^a-zA-Z]+"),这样非字母字符作为分隔符。然后统计每个单词的出现次数。使用HashMap,遍历单词数组,如果单词已经存在,就增加计数,否则设为1。然后排序,将entrySet转为List,用Collections.sort,自定义Comparator,比较两个Entry的值,降序排列。最后遍历排序后的列表,输出结果。
可能的代码结构如下:
1. 读取文件内容,存为字符串。
2. 用正则表达式分割成单词数组。
3. 统计频率。
4. 排序。
5. 输出。
需要处理可能的异常,比如文件不存在,IO异常等,用try-catch块处理。
测试例子是否符合预期,比如输入“Hello word Hello”,应该输出Hello:2,word:1。如果代码区分大小写,那么是正确的。如果输入中有“hello”则会单独统计。用户可能需要不区分大小写,这时候需要在统计前将单词转为小写,但输出时保留原样可能困难,因为无法知道原始形式。或者用户接受统一输出小写形式。这个问题需要确认,但用户例子中的输出是保留原大小写的,所以可能应该统计时区分大小写。但用户的需求可能有不同的情况,可能需要代码灵活处理。不过根据例子,暂时按区分大小写处理。
代码示例:
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.*;
import java.util.stream.Collectors;
public class WordFrequencyCounter {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("document.txt"))) {
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
content.append(line).append(" ");
}
String[] words = content.toString().split("[^a-zA-Z]+");
Map<String, Integer> frequencyMap = new HashMap<>();
for (String word : words) {
if (!word.isEmpty()) {
frequencyMap.put(word, frequencyMap.getOrDefault(word, 0) + 1);
}
}
List<Map.Entry<String, Integer>> sortedList = new ArrayList<>(frequencyMap.entrySet());
sortedList.sort((a, b) -> b.getValue().compareTo(a.getValue()));
for (Map.Entry<String, Integer> entry : sortedList) {
System.out.println(entry.getKey() + ": " + entry.getValue() + " 次");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
这里需要注意几点:
1. 分割时使用split("[^a-zA-Z]+"),这样连续的字母组成单词,非字母作为分隔符。但可能单词中有撇号,比如“don't”会被分割成“don”和“t”,这可能不正确。用户的需求是否需要考虑这种情况?如果英文文档包含这类单词,可能需要调整正则表达式。比如使用split("[^a-zA-Z']+"),保留撇号。但用户可能没有提到,所以暂时按原代码处理。
2. 空字符串的处理:split可能会生成空字符串,所以需要检查word是否为空。
3. 排序部分用了Lambda表达式,按值降序排列。
4. 输出格式与例子一致,比如“Hello:2 次”。
用户可能的问题包括如何处理大小写,如何处理带标点的单词,比如“word.”会被分割成“word”,是否正确。这些可能需要根据实际需求调整正则表达式。
此外,如果用户需要忽略大小写,可以将word转换为小写,即frequencyMap.put(word.toLowerCase(), ...),但输出时所有单词都会是小写形式。但用户例子中的输出保留原大小写,所以可能应该统计原单词,但这样“Hello”和“hello”会被视为不同。用户可能需要忽略大小写,但例子中的输入没有这种情况,所以可能需要进一步询问用户,但根据当前信息,先按原样处理。
综上,代码应该能够满足用户给出的例子,但可能需要根据实际需求调整单词分割的方式和大小写处理。</think>以下是实现该需求的完整 Java 代码及分步说明:
---
### **实现步骤**
1. **读取文档内容**
使用 `BufferedReader` 读取文本文件
2. **分割单词**
用正则表达式 `\\W+` 分割非字母字符
3. **统计词频**
通过 `HashMap` 存储单词及其出现次数
4. **排序结果**
将词频按从高到低排序,使用 `Stream` 或 `Comparator`
5. **输出结果**
格式化打印排序后的统计结果
---
### **完整代码**
```java
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
public class WordCounter {
public static void main(String[] args) {
// 1. 读取文件内容
String content = readFile("document.txt");
if (content == null) return;
// 2. 分割单词 (正则表达式分割非字母字符)
String[] words = content.split("[\\W]+"); // 排除标点符号
// 3. 统计词频 (区分大小写)
Map<String, Integer> frequencyMap = new HashMap<>();
for (String word : words) {
if (!word.isEmpty()) {
frequencyMap.put(word, frequencyMap.getOrDefault(word, 0) + 1);
}
}
// 4. 按频率排序 (降序)
List<Map.Entry<String, Integer>> sortedList = frequencyMap.entrySet()
.stream()
.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
.collect(Collectors.toList());
// 5. 输出结果
System.out.println("统计结果:");
for (Map.Entry<String, Integer> entry : sortedList) {
System.out.printf("%s: %d 次\n", entry.getKey(), entry.getValue());
}
}
private static String readFile(String filePath) {
StringBuilder content = new StringBuilder();
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = br.readLine()) != null) {
content.append(line).append(" ");
}
return content.toString();
} catch (IOException e) {
System.err.println("文件读取失败: " + e.getMessage());
return null;
}
}
}
```
---
### **关键点说明**
1. **单词分割逻辑**
- 正则表达式 `[\\W]+` 会匹配所有**非字母、数字、下划线**的字符,确保正确分割单词
- 如需忽略大小写,可在统计前添加:
```java
word = word.toLowerCase(); // 统一转小写
```
2. **排序优化**
使用 Java 8 的 `Stream` + `Lambda` 简化排序代码,替代传统 `Comparator` 写法
3. **扩展性处理**
- 空字符串过滤:`if (!word.isEmpty())` 防止统计空白字符
- 文件异常处理:通过 `try-with-resources` 自动关闭流
---
### **示例运行**
输入文件 `document.txt` 内容:
```
Hello world Hello! This is a test. Test is important.
```
输出结果:
```
统计结果:
Hello: 2 次
is: 2 次
world: 1 次
This: 1 次
a: 1 次
test: 1 次
Test: 1 次
important: 1 次
```
---
### **自定义需求调整**
1. **忽略大小写**
在统计前添加 `word = word.toLowerCase();`
输出结果将合并大小写不同的单词(例如 `Test` 和 `test`)
2. **排除短词**
添加过滤条件:
```java
if (word.length() < 3) continue; // 忽略长度小于3的单词
```
3. **支持命令行参数**
修改 `main` 方法接收文件路径:
```java
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("请指定文件路径");
return;
}
String content = readFile(args[0]);
// ...后续代码不变
}
```
通过调整代码逻辑,可灵活满足不同统计需求。
阅读全文
相关推荐

















